【问题标题】:Why destructor of a moved from object is invoked?为什么调用从对象移动的析构函数?
【发布时间】:2014-08-26 06:20:51
【问题描述】:

考虑以下代码:

struct foo {
  std::string id;
};

int main() {
  std::vector<foo> v;

  {
    foo tmp;
    v.push_back(std::move(tmp));
  }
}

LIVE DEMO

在演示的这段代码中:

  1. 将调用类foo的默认构造函数来构造对象tmp
  2. foo 类的移动构造函数将在语句v.push_back(std::move(tmp)); 中调用。
  3. class foo 的析构函数将被调用两次。

问题:

  1. 为什么移动对象的析构函数被调用两次?
  2. 真正从正在移动的对象中移动了什么?

【问题讨论】:

  • 被移动的对象只被破坏一次。每个对象都创建一次,销毁一次。两个析构函数调用是针对tmp 和向量中的对象。

标签: c++ c++11 move


【解决方案1】:

为什么移动对象的析构函数会被调用两次?

main() 中的第一个 } 超出范围时,第一个析构函数会销毁已移动的 tmp。当v 超出范围时,第二个析构函数破坏了移动构造的foo,您push_backmain() 的末尾将其转换为v

真正从被移动的对象中移动了什么?

编译器生成的移动构造函数move-constructs id,它是一个std::stringstd::string 的移动构造函数通常获取存储实际字符串的被移动对象中的内存块的所有权,并将被移动对象设置为有效但未指定的状态(实际上,可能是空字符串)。

【讨论】:

  • "destroys tmp, after it's beenmoved from":好吧,它是由于离开作用域(push_back 之后的})而被销毁的,而不是在它被移出后立即被销毁( ; 在 push_back 之后)。如果push_back} 之间有更多代码,这很重要。
  • @AndreKostur 我并不是要暗示tmp 被移出和tmp 被破坏之间存在偶然联系;这旨在解释为什么 OP 演示中的第一个析构函数输出打印出一个空字符串,并描述 tmp 在其销毁时的状态。不过,我发现它可能会造成混淆,因此请澄清一下。
猜你喜欢
  • 2016-11-23
  • 2010-10-16
  • 1970-01-01
  • 2023-03-18
  • 2014-06-13
  • 1970-01-01
  • 2019-01-29
  • 2020-11-05
  • 1970-01-01
相关资源
最近更新 更多