移动语义==自定义交换功能已过时?

Xeo*_*Xeo 31 c++ swap obsolete move-semantics c++11

最近,许多 问题 弹出如何提供自己的swap功能.使用C++ 11,std::swap将使用std::move和移动语义以尽可能快地交换给定值.当然,这仅适用于提供移动构造函数和移动赋值运算符(或使用按值传递的运算符)的情况.

现在,有了这个,是否真的有必要swap在C++ 11中编写自己的函数?我只能想到不可移动的类型,但是再一次,自定义swaps通常通过某种"指针交换"(也就是移动)来工作.也许有某些参考变量?嗯...

How*_*ant 22

这是一个判断问题.我通常会让std::swap原型代码完成工作,但是对于发布代码,请编写自定义交换.我通常可以写一个自定义交换,大约是1移动构造的两倍+ 2个移动分配+ 1个无资源的破坏.然而std::swap,在打扰之前,人们可能要等到实际证明是性能问题.

Alf P. Steinbach的更新:

20.2.2 [utility.swap]指定std::swap(T&, T&)具有noexcept等效于:

template <class T>
void
swap(T& a, T& b) noexcept
                 (
                    is_nothrow_move_constructible<T>::value &&
                    is_nothrow_move_assignable<T>::value
                 );
Run Code Online (Sandbox Code Playgroud)

也就是说,如果移动操作上Tnoexcept,然后std::swapTnoexcept.

请注意,此规范不需要移动成员.它只需要从rvalues构造和赋值,如果存在noexcept,则交换将是noexcept.例如:

class A
{
public:
    A(const A&) noexcept;
    A& operator=(const A&) noexcept;
};
Run Code Online (Sandbox Code Playgroud)

std::swap<A> 即使没有移动成员,也是不存在的.

  • @Alf:不; 他给出了一个例子,其中`std :: swap`将是'noexcept(true)`,即使没有实际的移动构造/赋值. (3认同)
  • @Alf:`is_nothrow_move_constructible <T>`与`is_nothrow_constructible <T,T &&>`相同.复制构造函数的传统`T(const T&)`版本接受r值引用就好了,因此`T`将报告为可移动构造,即使实际移动没有发生.从`is_nothrow_move_assignable <T>`到`is_nothrow_assignable <T,T &&>`执行类似的映射,因此在那里应用相同的参数. (2认同)