C++核心准则C.62:保证拷贝赋值对自我赋值安全
C.62:保证拷贝赋值对自我赋值安全
If x = x changes the value of x, people will be surprised and bad errors will occur (often including leaks).
如果x=x改变了x的值,人们会觉得很奇怪,同时也会发生很不好的错误。(通常会包含泄露)
The standard-library containers handle self-assignment elegantly and efficiently:
标准库容器处理自我赋值的方式优雅且高效:
std::vector v = {3, 1, 4, 1, 5, 9};
v = v;
// the value of v is still {3, 1, 4, 1, 5, 9}
The default assignment generated from members that handle self-assignment correctly handles self-assignment.
产生于正确处理了自我赋值的成员的默认的赋值操作会处理自我赋值问题。
struct Bar {
vector> v;
map m;
string s;
};
Bar b;
// ...
b = b; // correct and efficient
You can handle self-assignment by explicitly testing for self-assignment, but often it is faster and more elegant to cope without such a test (e.g., using swap).
你可以通过明确地对自我赋值进行检查的方式防止自我赋值,但是通常不使用上述检查的处理方式(例如使用swap)的方式更快,更优雅。
class Foo {
string s;
int i;
public:
Foo& operator=(const Foo& a);
// ...
};
Foo& Foo::operator=(const Foo& a) // OK, but there is a cost
{
if (this == &a) return *this;
s = a.s;
i = a.i;
return *this;
}
This is obviously safe and apparently efficient. However, what if we do one self-assignment per million assignments? That's about a million redundant tests (but since the answer is essentially always the same, the computer's branch predictor will guess right essentially every time). Consider:
这种做法看起来安全并且高效。但是如果在一百万次赋值中只发生一次自我赋值的情况下会怎么样呢?大概有一百万次多余的检查(但是由于本质上结果总是一样的,计算机的分支预测会每次都猜对)。考虑下面的代码:
Foo& Foo::operator=(const Foo& a) // simpler, and probably much better
{
s = a.s;
i = a.i;
return *this;
}
std::string is safe for self-assignment and so are int. All the cost is carried by the (rare) case of self-assignment.
std::string对自我赋值安全,int也是。所有的代价都来自(极少)发生的自我赋值。
(Simple) Assignment operators should not contain the pattern if (this == &a) return *this; ???
(简单)赋值运算符不应该包含以下的检查:if (this == &a) return *this;
觉得本文有帮助?请分享给更多人。
关注【面向对象思考】轻松学习每一天!
面向对象开发,面向对象思考!