我想我不懂移动语义学。给定以下代码,我希望调试器(MSVC2010SP1)按以下顺序调用代理的成员:
Proxy(Resource*)在getProxy中构造临时Proxy(Proxy&& other)移动构造p~Proxy()破坏了临时的空壳,移动占据了它的内脏。~Proxy() p超出了范围
类资源{ void (){} public: void (){} Proxy& getProxy();};类代理{资源*pResource_;代理(const*pResource_&其他);//禁用代理& operator=(const Proxy&其他);//禁用公共: Proxy(Resource *pResource):pResource_(pResource){} Proxy( Proxy& & *pResource_= nullptr;} ~ Proxy () { if( pResource_ ) pResource_->close();pResource_= nullptr;};Proxy& Resource::getProxy() { open();返回代理(This);} //在其他地方,例如in main() Resource r;{ auto = r.getProxy();}//p超出了范围相反,命令是:
Proxy(Proxy*)~Proxy() //这已经比预期更早地调用了close()Proxy(Proxy&& other) //破坏后移动给p.pResource_一个nullptr值~Proxy() //p超出范围这对我来说毫无意义。我要做的是跟踪代理类的生存期,通过将构造函数从一个对象转移到另一个对象,传递关闭资源的任务。
发布于 2013-02-04 14:23:52
getProxy()返回一个临时引用,该引用在函数结束时超出作用域,并导致一个悬空引用。
发布于 2013-02-04 14:34:50
按rvalue引用返回实际上不会导致任何移动。它只是以引用的方式返回。但是,它与返回lvalue引用不同,因为调用返回rvalue引用的函数的表达式是xvalue (与lvalue相反)。然后可以将xvalue (作为rvalue表达式的子集)移出。如果要从返回lvalue引用的函数的返回对象中移动,则必须使用std::move使其成为rvalue。
您很少会想要实际返回一个rvalue引用。它唯一含糊的常见用途是允许对象的私有成员被移出。如果希望在从函数返回对象时移动对象,只需按值返回。在您的示例中,如果getProxy的返回类型只是Proxy,则临时的将从返回的对象移到返回的对象中,然后从返回的对象移到p中(除任何省略外)。
正如您所拥有的,临时对象(由Proxy(this)构造)在return语句的末尾被销毁--这是析构函数的第一次调用。返回的引用现在引用的是一个无效的对象,而p是通过从这个无效的引用中移动来构造的。这给了你不确定的行为。
https://stackoverflow.com/questions/14688598
复制相似问题