CppCoreGuidelines C.62 拷贝赋值操作要能安全的自赋值
28 October 2022
C.62: Make copy assignment safe for self-assignment
理由
如果x = x
这样的操作会改变 x
的值,那么人们会感到惊讶,也可能导致大的错误,比如内存泄漏。
例子
标准库的容器能够优雅高效的处理自赋值情况:
std::vector<int> v = {3, 1, 4, 1, 5, 9}; v = v; // the value of v is still {3, 1, 4, 1, 5, 9} std::for_each(v.cbegin(), v.cend(), [](const int &n){cout << n << " ";});
3 1 4 1 5 9
注意
默认赋值操作的正确执行是基于其成员能够正确处理自赋值情况。
struct Bar { vector<pair<int, int>> v; map<string, int> m; string s; }; Bar b; // ... b = b; // correct and efficient cout << b.v.size();
0
注意
你可以显式地测试自赋值情况,但是更快更优雅的方式是免去测试是否自赋值的情况。
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; }
以上做法很安全,且看起来很高效。但是如果我们进行几百万次的自赋值操作会怎么样?以上例子中的判断是不是对象自己这个操作会重复几百万次。尽管编译器可能会根据实际情况进行优化。可以考虑用以下方式实现:
Foo& Foo::operator=(const Foo& a) // simpler, and probably much better { s = a.s; i = a.i; return *this; }
std::string
像 int
类型一样,可以安全应对自赋值操作。
强化
- (简单)自赋值操作的实现中不需要有
if (this == &a) return *this
这样的操作。