self assign
大多数时候自赋值的检查是没有必要的,尤其是没有使用什么裸指针类型之类的。如果你自己的类里面全部是高级的类型,没有必要自己重载operator=
但有一种情况,一个类持有一个指针,且掌控这个指针的生命周期,这时候就需要自己重载operator=,来避免自赋值的情况。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class T {
int* p;
public:
T(const T &rhs) : p(rhs.p ? new int(*rhs.p) : nullptr) {}
~T() { delete p; }
// ...
T& operator=(const T &rhs) {
delete p;
p = new int(*rhs.p);
return *this;
}
};
上述的行为有两种办法可以处理,第一种就是自赋值检查
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class T {
int* p;
public:
T(const T &rhs) : p(rhs.p ? new int(*rhs.p) : nullptr) {}
~T() { delete p; }
// ...
T& operator=(const T &rhs) {
if(this == &rhs)
return *this;
delete p;
p = new int(*rhs.p);
return *this;
}
};
第二种就是copy-swap
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class T {
int* p;
public:
T(const T &rhs) : p(rhs.p ? new int(*rhs.p) : nullptr) {}
~T() { delete p; }
// ...
void swap(T &rhs) {
using std::swap;
swap(p, rhs.p);
}
T& operator=(const T &rhs) {
T(rhs).swap(*this);
return *this;
}
};
还有一种就是产生一个临时变量,然后move过去,这种看起来不是很优雅…
其实看看msvc的STL库里的自赋值是怎么做的就知道了,容器看起来都加了addressof是不是相等的检查,但是智能指针都是直接swap的,而且+了noexcept的声明
另外自己写不是确定的话,不要+noexcept,步子大了容易扯着蛋
- move之类的可以+
- swap的可以加
别的都别想了,c++11之后析构函数应该都默认+了noexcept的了
REF
This post is licensed under CC BY 4.0 by the author.