跳到主要内容

优雅的处理自我赋值

· 阅读需 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;
}
};

未完待续。。。