std :: swap()可以安全地用于对象吗?

时间:2015-04-15 10:16:18

标签: c++ copy-constructor

在这个关于复制和交换的question中,接受的答案中有一个swap()函数。

friend void swap(dumb_array& first, dumb_array& second) // nothrow
 {
    // enable ADL (not necessary in our case, but good practice)
    using std::swap; 

    // by swapping the members of two classes,
    // the two classes are effectively swapped
    swap(first.mSize, second.mSize); 
    swap(first.mArray, second.mArray);
}

为什么不只是std::swap(first, second)

2 个答案:

答案 0 :(得分:7)

std::swap依赖于赋值运算符。因此,如果赋值运算符要调用std::swap,这将导致赋值运算符与std::swap之间来回的无限调用。

关于标题中的问题。是的,对于具有值语义的行为良好的类,可以安全地在该类的对象上调用std::swap。由于上述原因,只有该类的实施者不能将其用于复制和交换习语。

答案 1 :(得分:1)

C ++ 98建议使用代码片段,在同一个答案中还有另一个C ++ 11(移动语义)的建议。

Scott Meyers的Effective C ++书中很好地解释了为C ++ 98解决方案提供swap()函数的原因。

简言之;

  template<typename T>          // typical implementation of std::swap;
  void swap(T& a, T& b)         // swaps a's and b's values
  {
    T temp(a);
    a = b;
    b = temp;
  }
  

只要您的类型支持复制(通过复制构造函数和复制   赋值运算符),默认的交换实现会让对象   您的类型将被交换​​,而无需您进行任何特殊工作   支持它。

     

但是,默认的交换实现可能不会让您感到兴奋。它   涉及复制三个对象:a到temp,b到a,temp到b。对于   某些类型,这些副本都不是必需的。对于这种类型,   默认交换使您快速通往慢车道。

     

这些类型中最重要的是主要由指针组成的类型   到另一种包含真实数据的类型。一种常见的表现形式   这种设计方法是“pimpl成语”......