是所有基于std :: move()的std :: swap()实现我都看到了错误吗?

Meh*_*dad 3 c++ swap move-constructor move-semantics c++11

可能重复:
移动对象有什么用处?

例如,请参阅以下代码:

template<class T> 
void swap(T& a, T& b) 
{ 
    T tmp(std::move(a));
    a = std::move(b); 
    b = std::move(tmp);
} 
Run Code Online (Sandbox Code Playgroud)

它只是我,还是有错误?如果你move a进入tmp,那么不会a变得无效?

即不得布展分配ab一招-构造函数调用与安置new呢?
如果没有,那么移动构造函数和移动赋值运算符之间有什么区别?

template<class T>
void swap(T& a, T& b)
{
    T tmp(std::move(a));
    new(&a) T(std::move(b));
    new(&b) T(std::move(tmp));
}
Run Code Online (Sandbox Code Playgroud)

tem*_*def 9

当您从对象移出数据时,预期的语义是移动的对象最终处于未指定但有效的状态.这意味着你无法预测对象将处于什么状态,除了它将是一个格式良好的对象.这与"这个物体已经死了,不见了"并不完全相同.将数据移出对象不会终止对象的生命周期 - 它只是将其状态更改为未指定的状态 - 因此,为该对象分配新值是完全安全的.

因此,交换功能的初始版本是安全的.从a移动数据后,该对象保留一些未指定的"安全但不可预测"的值.移动时,该值将被覆盖,并将其赋值为b.

第二个版本是不安全的,因为在您尝试在其上构建新对象之前,a的生命周期尚未结束.这导致未定义的行为.

希望这可以帮助!

  • @Xeo不确定你在这里的意思,但是从一个物体移动绝对不会*结束它的生命周期.析构函数启动时生命周期结束,当您从对象移动时不会发生这种情况. (2认同)

Man*_*Way 6

a仍然有效.a尽管如此,其中的数据将不再可靠.a移动资源时不会释放,因此将新资源移动到完全没问题a.

  • 它不是'a`被移动,它是'a`中的资源.如果你在某个内存中有一个指针,例如`a-> data`,你将`data`移动到另一个对象,`a`仍然存在. (3认同)
  • @Mehrdad一个创建一个新对象,另一个不创建? (2认同)

Ker*_* SB 5

移动不会使对象无效.相反,它总体上仍处于有效但不确定的状态.特定班级有额外保证; 例如,std::unique_ptr保证从移动后它将为null.

保留有效对象尤其意味着分配给对象是完全正确的,这是原始代码所做的.

您自己提出的解决方案严重破坏:当您在旧对象上放置构造新对象时,旧对象的生命周期结束.但是,如果类的析构函数有效,那么省略调用析构函数是未定义的行为.

此外,如果你首先正确地调用了析构函数,但是在构造函数中遇到异常,那么你就会遇到麻烦,因为你现在没有一个需要在范围退出时销毁的有效对象.这是我在这个主题上的一个相关问题.