赋值运算符 - 自赋值
Posted
技术标签:
【中文标题】赋值运算符 - 自赋值【英文标题】:Assignment operator - Self-assignment 【发布时间】:2011-08-02 06:54:03 【问题描述】:编译器生成的赋值运算符是否防止自赋值?
class T
int x;
public:
T(int X = 0): x(X)
;
int main()
T a(1);
a = a;
即使类成员不是指针类型,我是否总是需要防止自赋值?
【问题讨论】:
不,这没有什么问题。而且我认为没有什么可以“防范”,真的。编辑:您是在谈论复制构造函数吗? 如果没有类成员是指针/智能类型,那么答案是否定的。无需防范它。在这种情况下,行为与 POD(普通旧数据)相同...... 【参考方案1】:编译器生成的赋值运算符是否防止自赋值?
不,它没有。它仅执行成员方式的复制,其中每个成员都由其自己的赋值运算符(也可能是程序员声明的或编译器生成的)进行复制。
即使类成员不是指针类型,我是否总是需要防止自赋值?
不,如果您的所有类的属性(以及它们的属性)都是POD-types,则您不需要。
在编写您自己的赋值运算符时,如果您希望自己的类在未来得到验证,您可能希望检查自赋值,即使它们不包含任何指针,等等。也可以考虑the copy-and-swap idiom。
【讨论】:
添加、删除或更改数据成员无论如何都需要您重新访问 op=(以及其他),因此就未来的验证而言,不必要的自分配检查没有任何好处。 @Johnsyweb:添加不必要的自我分配检查也不能保证维护者会做正确的事情,但更可能让知道他们在做什么的人感到困惑。例如:“不必要”在这里很重要,因为复制经常(很少)自分配的类型会从检查中受益,即使它不是绝对必要的。 或者重申:未来的维护者总是能够把事情搞砸,担心他们可能会或可能不会做的事情是没有效率的。保持更新、有用的文档和编写清晰的代码是您所能做的。 @Fred Nurk:完全同意。对于“更新的、有用的文档”,我阅读了“单元测试”:-) 如果所有成员(包括基类)都处理自己的任务,那么您将无事可做。编译器将通过依次调用每个成员的运算符/构造函数来生成成员复制和赋值。这很好用。有时人们认为自我分配测试是一种优化,但它也可能是一种悲观化——为所有分配添加额外的检查。如果自赋值非常普遍,也许我们应该看看使用赋值的代码。 :-)【参考方案2】:这很容易凭经验检查:
#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;
【讨论】:
不错!这无疑展示了 current 编译器的行为。【参考方案3】:class T
int x;
public:
T(int X = 0): x(X)
// prevent copying
private:
T& operator=(const T&);
;
【讨论】:
在我看来 cpx 并不想禁用赋值运算符。 (S)他想使用它,但有一个关于自我分配的问题。 (此外,您的代码有错字。)以上是关于赋值运算符 - 自赋值的主要内容,如果未能解决你的问题,请参考以下文章