重载C ++赋值运算符的最佳方法

时间:2013-03-12 07:54:06

标签: c++ operator-overloading assignment-operator

我有一个类A,它在构造函数中为一个整数(由类memeber指出_pPtrMem指向)动态分配内存,并在析构函数中释放相同的内容。为了避免Shallow复制,我重载了赋值运算符和复制构造函数。赋值运算符过载的广泛使用方式如下:

A& operator = (const A & iToAssign)
{
  if (this == & iToAssign)  // Check for self assignment
    return *this;
  int * pTemp = new int(*(iToAssign._pPtrMem)); // Allocate new memory with same value
  if (pTemp)
  {
    delete _pPtrMem;  // Delete the old memory
    _pPtrMem = pTemp; // Assign the newly allocated memory
  }
  return *this;   // Return the reference to object for chaining(a = b = c)
}

实现相同的另一种方法可能是

A& operator = (const A & iToAssign)
{
  *_pPtrMem= *(iToAssign._pPtrMem); // Just copy the values
  return *this;   
}

由于第二个版本相对简单得多,速度更快(没有解除分配,内存分配),为什么不广泛使用?我无法解决的任何问题?

此外,我们从赋值运算符返回相同类型的对象进行链接(a = b = c)...所以不是返回 *这个就可以返回 iToAssign 对象,因为两个对象现在都相等?

5 个答案:

答案 0 :(得分:6)

通常,实现复制赋值运算符的最佳方法是为您的类提供swap()函数(如果符合您的要求,则使用标准函数),然后通过副本实现复制赋值运算符构造:

A& A::operator= (A iToAssign)  // note pass by value here - will invoke copy constructor
{
  iToAssign.swap(*this);
  return *this;
}
// void swap(A& other) throws() // C++03
void A::swap(A& other) noexcept
{
    std::swap(_pPtrMem, other._pPtrMem);
}

这可以确保您的复制赋值运算符和复制构造函数永远不会发生分歧(也就是说,您不能更改一个并忘记更改另一个)。

答案 1 :(得分:1)

第一个版本用于_pPtrMem是指向某些基本类型的指针,例如动态分配的数组。如果指针指向具有正确实现的赋值运算符的单个对象,则第二个版本将同样好。但在这种情况下,我认为你根本不需要使用指针。

答案 2 :(得分:1)

不,您的实施没有问题。但是分配一个整数动态至少非常特殊。

此实现未广泛使用,因为没有人在免费商店上分配单个整数。对于在编译时未知的可变长度的数组,通常使用动态分配的内存。在这种情况下,大多数情况下使用std :: vector是个好主意。

不,它不好,返回一个不同的对象。身份与平等不同:

T a, b, d;
T& c = a = b;
c = d; // should change a, not b 

您是否希望第三行改变b?

或更好的事件示例:

T a;
T& b = a = T();

这将导致悬挂引用,引用临时和被破坏的对象。

答案 3 :(得分:0)

在第二种情况下,如果_pPtrMem最初未取消分配,则行

*_pPtrMem= *(iToAssign._pPtrMem); // Just copy the values

导致分配到无效的内存位置(可能是分段错误)。只有在此次调用之前已为_pPtrMem分配内存时,此操作才有效。

答案 4 :(得分:0)

在这种情况下,第二种实施方式是更好的。 但是在对象中使用动态的通常原因是因为 大小可能会有所不同。 (另一个原因是因为你想要 浅拷贝的参考语义。)在这种情况下, 最简单的解决方案来使用你的第一个任务(没有 测试自我分配)。有人可能根据具体情况而定 考虑重新使用新值时已经存在的内存 会合适;它有点增加了复杂性(因为你必须这样做) 测试它是否合适,并且仍然可以 分配/复制/删除,如果没有),但它可以改善 在某些情况下的表现。