不在copy assignemt操作符中检查对象是否已分配给它自己真的安全吗



以下是我发现的实现"三条规则"的示例:

class Array { 
public: 
int size; 
int* vals;
Array() : size(0), vals(NULL){}
Array( int s, int* v );
Array(const Array&); // 1
Array& operator=(const Array&); // 2
~Array(); // 3
}; 
Array::~Array() { 
delete []vals; 
vals = NULL; 
} 
Array::Array( int s, int* v ){
size = s; 
vals = new int[size]; 
std::copy( v, v + size, vals ); 
} 
Array::Array(const Array& rhs):
size(rhs.size),
vals((rhs.size) ? new int[size] : NULL)
{
if(size)
std::copy(rhs.vals, rhs.vals + rhs.size, vals);
}
Array& Array::operator=(const Array& rhs){
//  if(this == &rhs) // no need
//      return *this;
int* a = (rhs.size)? new int[rhs.size] : NULL; // this is why we don't need the above check: if this line throws then vals is untouched. if this is ok (local variable) then continue (next won't throw).
std::copy(rhs.vals, rhs.vals + rhs.size, a); // copying to a even (self assignment won't harm)
delete[] vals;
vals = a;
size = rhs.size;
return *this;
}

正如您在上面看到的那样,复制分配运算符中的检查被删除,因为创建本地变量,然后删除成员指针并为其分配本地指针。但如果我写的话,重要的是什么:

int main() {
int vals[ 4 ] = { 11, 22, 33, 44 };  
Array a1( 4, vals ); 
a1 = a1; // here I assigned a1 to itself
return 0;
}

我将a1分配给它自己,这是否意味着a1vals被删除,然后在Copy分配运算符中分配给本地的a?这是正确的方式吗?我的代码有陷阱吗?

  • 如有任何建议,我们将不胜感激

复制赋值运算符将发挥作用,因为自赋值将具有预期的行为:数组的值内容将保持不变。

不进行测试所带来的损失是,如果您已经拥有一个数组,您将分配一个不需要的数组,执行一个不必执行的复制,然后销毁您本可以保留的东西。

这对性能是否重要。。。这将在很大程度上取决于使用相关因素。毕竟,如果您执行自复制,这只是一个问题。你多久做一次?如果你真的不经常(或永远(这样做,那么测试只是一个你不需要的条件分支。

同时,考虑vector的定义。当vector中的迭代器/指针/引用无效时,它有非常特殊的情况。复制vector不是其中之一。因此,如果对象存储的位置是数组类型接口的一部分(就像vector一样(,那么进行自复制对接口有更广泛的影响。

相关内容

最新更新