物体在移动操作前被破坏

时间:2015-09-01 16:25:37

标签: c++11

#include <iostream>
static int i=0;
using namespace std;
class Movable
{
public:
    Movable ():mId(++i){
        cout<<"constructing it "<<mId<<endl;
    };
    Movable (const Movable&)=delete;
    Movable (Movable&)=delete;
    void operator=(Movable&)=delete;
    void operator=(const Movable&)=delete;

    Movable (const Movable&& aObject)
    {
        cout<<"Moving it constant "<<mId<<endl;
//      mId=++i;
    };
    Movable (Movable&&aObject)
    {
        cout<<"Moving it "<<mId<<endl;
    };
    Movable &operator=( Movable&&aObject)
    {
        cout<<"Moving it assignment "<<mId<<endl;
        return *this;

    }
    Movable &operator=(const Movable&&aObject)
    {
        cout<<"Moving it assignment constant "<<mId<<endl;
        return *this;

    }
    ~Movable ()
    {
        cout<<"destroying it "<<mId<<endl;
    }

    int getId() const {
        return mId;
    }

private:
    int mId;
};

Movable&& CreatenNewMovable ()
{
    Movable lM;
    return std::move(lM);
}

int main() {
    Movable a;

    a=CreatenNewMovable();

    return 0;
}

此代码的输出结果为

constructing it 1
constructing it 2
destroying it 2
Moving it assignment 1
destroying it 1

我有点困惑如何破坏临时对象然后将其移动到第二位。这是一个未定义的行为吗?我错过了关于移动操作的事情吗?

2 个答案:

答案 0 :(得分:2)

是的,这个功能

Movable&& CreatenNewMovable ()
{
    Movable lM;
    return std::move(lM);
}

坏了。

r值引用仍然是引用,在这种情况下它是对本地堆栈对象的引用,该对象在函数终止时(在移动之前)被销毁。相反,你应该按值返回它,它仍然会被移出,如果有复制椭圆,那么它将是有效的。

答案 1 :(得分:2)

请看这个片段:

ObjectDisposedException

实际上这是未定义的行为。有两个问题:

  1. 函数只能通过值(可能是参考值)返回其值。因此,您必须在此Movable&& CreatenNewMovable () { Movable lM; return std::move(lM); } 替换Movable&&
  2. 在堆栈上创建Movable并在函数外部引用它是UB。当函数退出时,该对象不再存在。只需按值返回 - 在您的情况下,复制省略将生效。
  3. 最后,一个有效的方法是:

    Movable lM;

    这将产生您正在等待的结果:

    Movable CreatenNewMovable ()
    {
        Movable lM;
        return lM;
        // ..or..
        // Even better to return like this(copy elision has less chances to fail)
        // return Movable();
    }
    

    您可以通过删除$ ./w constructing it 1 constructing it 2 Moving it assignment 1 destroying it 2 destroying it 1 中的空对象创建来减少此作业:

    main