|
|
简体中文版翻译:申旻,nicrosoft@sunistudio.com(东日制作室,东日文档)
自赋值就是将对象赋值给本身。例如,
#include "Fred.hpp" // 声明 Fred 类
void userCode(Fred& x)
{
x = x; // 自赋值
}
很明显,以上代码进行了显式的自赋值。但既然多个指针或引用可以指向相同对象(别名),那么进行了自赋值而不知道的情况也是可能的:
#include "Fred.hpp" // 声明 Fred 类
void userCode(Fred& x, Fred& y)
{
x = y; // 如果&x == &y就可能是自赋值
}
int main()
{
Fred z;
userCode(z, z);
}
[ Top | Bottom | Previous section | Next section ]
如果不注意自赋值,将会使你的用户遭受非常微妙的并且一般来说非常严重的bug。例如,如下的类在自赋值的情况下将导致灾难:
class Wilma { };
class Fred {
public:
Fred() : p_(new Wilma()) { }
Fred(const Fred& f) : p_(new Wilma(*f.p_)) { }
~Fred() { delete p_; }
Fred& operator= (const Fred& f)
{
// 差劲的代码:没有处理自赋值!
delete p_; // Line #1
p_ = new Wilma(*f.p_); // Line #2
return *this;
}
private:
Wilma* p_;
};
如果有人将 Fred 对象赋给其本身,由于*this和 f 是同一个对象,line #1同时删除了this->p_和f.p_。而 line #2使用了已经不存在的对象*f.p_,这样很可能导致严重的灾难。
作为 Fred 类的作者,你最起码有责任确信在Fred对象上自赋值是无害的。不要假设用户不会在对象上这样做。如果对象由于自赋值而崩溃,那是你的过失。
另外:上述的Fred::operator= (const Fred&)还有第二个问题:如果在执行new Wilma(*f.p_)时,抛出了异常(例如,内存不够的异常或者Wilma的拷贝构造函数中的异常), this->p_将成为悬空指针——它所指向的内存不再是可用的。这可以通过在删除就对象前创建对象来解决。
[ Top | Bottom | Previous section | Next&nbs
网友评论:(评论内容只代表网友观点,与本站立场无关!) |
阅读排行
|