优雅的处理自我赋值
· 阅读需 2 分钟
之前写过一个简单的vector,Clang-tidy警告:
Operator=() does not handle self-assignment properly
为什么要警惕自我赋值呢?一个经典的例子是当你赋值的时候需要先删除原来的值时,不做处理的自我赋值就会造成错误。 例如如下代码:
class T {
int* p;
public:
// rhs 即 Right Hand Side 。
T(const T& rhs){
if(rhs.p) p = new int(*rhs.p);
else p = nullptr;
}
~T() { delete p; }
// ...
T& operator=(const T& rhs) {
delete p;
p = new int(*rhs.p);
return *this;
}
};
这时如果有一个T
类型的变量a
, 并且执行a = a
的话,就会出现错误。
一种显然的解决办法是,先判断是否为自己,如果是,则不做处理。 代码如下:
class T {
int* p;
public:
// rhs 即 Right Hand Side 。
T(const T& rhs){
if(rhs.p) p = new int(*rhs.p);
else p = nullptr;
}
~T() { delete p; }
// ...
T& operator=(const T& rhs) {
if (this == &rhs) return *this;
delete p;
p = new int(*rhs.p);
return *this;
}
};
这样的代码就完美了吗,并没有,
class T {
int* p;
public:
// rhs 即 Right Hand Side 。
T(const T& rhs) {
if (rhs.p)
p = new int(*rhs.p);
else
p = nullptr;
}
~T() { delete p; }
// ...
T& operator=(const T& rhs) {
if (this == &rhs) return *this;
delete p;
try {
p = new int(*rhs.p);
} catch (std::bad_alloc&) {
p = nullptr;
throw;
}
return *this;
}
};
未完待续。。。
links
- bugprone-unhandled-self-assignment:https://releases.llvm.org/13.0.0/tools/clang/tools/extra/docs/clang-tidy/checks/bugprone-unhandled-self-assignment.html
- OOP54-CPP. Gracefully handle self-copy assignment:https://wiki.sei.cmu.edu/confluence/display/cplusplus/OOP54-CPP.+Gracefully+handle+self-copy+assignment