使用std::swap()对对象安全吗?

3
在这个与copy-and-swap相关的问题中,答案中有一个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个回答

8

std::swap 依赖于赋值运算符。因此,如果赋值运算符调用 std::swap,就会导致在赋值运算符和 std::swap 之间的无限调用链。

关于您标题中的问题。是的,对于一个行为良好的具有值语义的类,安全地在该类的对象上调用 std::swap 是可行的。仅实现该类的人不能使用它进行复制和交换惯用语,原因如上所述。


std::swap确实会复制两边的内容。手动逐成员交换最多只会每次多复制一个成员,而在std::vector上则完全不需要复制(向量数据)。 - Yakk - Adam Nevraumont

1
代码片段建议使用C++98,同一答案中还有针对C++11的另一个建议(移动语义)。
在C++98解决方案中,为什么有swap()函数的原因在Scott Meyers的Effective C++书中有很好的解释。
简要地说;
  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习惯用法”...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接