#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
我有点困惑如何破坏临时对象然后将其移动到第二位。这是一个未定义的行为吗?我错过了关于移动操作的事情吗?
答案 0 :(得分:2)
是的,这个功能
Movable&& CreatenNewMovable ()
{
Movable lM;
return std::move(lM);
}
坏了。
r值引用仍然是引用,在这种情况下它是对本地堆栈对象的引用,该对象在函数终止时(在移动之前)被销毁。相反,你应该按值返回它,它仍然会被移出,如果有复制椭圆,那么它将是有效的。
答案 1 :(得分:2)
请看这个片段:
ObjectDisposedException
实际上这是未定义的行为。有两个问题:
Movable&& CreatenNewMovable ()
{
Movable lM;
return std::move(lM);
}
替换Movable&&
。Movable
并在函数外部引用它是UB。当函数退出时,该对象不再存在。只需按值返回 - 在您的情况下,复制省略将生效。最后,一个有效的方法是:
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