首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当返回临时(rvalue)时,为什么在移动构造函数之前调用析构函数?

当返回临时(rvalue)时,为什么在移动构造函数之前调用析构函数?
EN

Stack Overflow用户
提问于 2013-02-04 14:17:01
回答 2查看 1.6K关注 0票数 2

我想我不懂移动语义学。给定以下代码,我希望调试器(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超出范围

这对我来说毫无意义。我要做的是跟踪代理类的生存期,通过将构造函数从一个对象转移到另一个对象,传递关闭资源的任务。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-02-04 14:23:52

getProxy()返回一个临时引用,该引用在函数结束时超出作用域,并导致一个悬空引用。

票数 6
EN

Stack Overflow用户

发布于 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是通过从这个无效的引用中移动来构造的。这给了你不确定的行为。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14688598

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档