2011-04-09 113 views
13

编译器是否生成赋值运算符防止自赋值?赋值运算符 - 自赋值

class T { 

    int x; 
public: 
    T(int X = 0): x(X) {} 
}; 

int main() 
{ 
    T a(1); 
    a = a; 
} 

即使类成员不是指针类型,我是否总是需要防止自赋值?

+1

没有,有什么不妥。我不认为有什么需要“防范”的,真的。编辑:你在说复制构造函数吗? – 2011-04-09 23:11:45

+2

如果没有类成员是指针/智能类型,那么答案是否定的。没有必要防止它。在这种情况下,行为与POD(普通旧数据)相同... – 0xC0000022L 2011-04-09 23:13:31

回答

12

编译器是否生成赋值操作符防止自赋值?

不,不。它只是执行一个成员方式的副本,其中每个成员都由自己的赋值运算符(也可能是程序员声明或编译器生成的)复制。

即使类成员不是指针类型,我是否总是需要防止自赋值?

不,如果你的班级的所有属性(因此他们的属性都是POD-types),你不会。

当写你自己的赋值操作符,你不妨检查一下自赋值,如果你想将来证明你的课,即使它们不包含任何指针,等等。另请考虑the copy-and-swap idiom

+1

无论如何,添加,删除或更改数据成员都需要重新访问op =(等等),因此不必要的自分配检查就像未来的保证一样。 – 2011-04-09 23:58:06

+0

@Fred Nurk:你是对的。不幸的是,重新访问'operator ='新的或改变的属性并不能保证维护者会做正确的事情。 – Johnsyweb 2011-04-10 00:08:05

+2

@Johnsyweb:添加一个不必要的自分配检查也不能保证维护者会做正确的事情,但更可能会困惑于知道他们在做什么的人。例如:“不必要”在这里很重要,因为复制类型经常是自行分配(罕见)的代价会受益于检查,即使它不是绝对必要的。 – 2011-04-10 01:30:40

4

这是一个容易凭经验检查:

#include <iostream> 
struct A { 
    void operator=(const A& rhs) { 
    if(this==&rhs) std::cout << "Self-assigned\n"; 
    } 
}; 

struct B { 
    A a; 
}; 

int main() 
{ 
    B b; 
    b = b; 
} 
+1

不错!这无疑证明了* current *编译器的行为。 – Johnsyweb 2011-04-10 02:02:13

-1
class T { 
    int x; 
public: 
    T(int X = 0): x(X) {} 
// prevent copying 
private: 
    T& operator=(const T&); 
}; 
+1

它似乎并不是我想要禁用赋值运算符。 (S)他想使用它,但有一个自我分配的问题。 (此外,你的代码有一个错字。) – 2012-06-14 08:05:09