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

10

请考虑以下代码片段:

struct foo {
  std::string id;
};

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

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

演示实况

在所示的代码中:

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

问题:

  1. 为什么已移动对象的析构函数会被调用两次?
  2. 被移动的对象到底是什么?

2
被移动的对象只会被析构一次。每个对象都只创建一次并且被析构一次。这两个析构函数调用是针对 tmp 和向量中的对象的。 - M.M
1个回答

2
为什么移动对象的析构函数会被调用两次?
第一个析构函数在main()函数中的第一个}处,当移动对象tmp超出作用域时,它将销毁。第二个析构函数在main()函数结束时,当v超出作用域时,销毁通过push_back添加到v中的move-constructed foo。
移动的对象实际上是什么?
编译器生成的移动构造函数move-constructs id,这是一个std::string。std::string的移动构造函数通常接管存储实际字符串的移动对象内存块,并将移动对象设置为有效但未指定状态(在实践中,可能是空字符串)。

在作用域结束后(push_back后的}),它会被销毁,而不是在移动之后立即销毁(push_back后的;)。如果在push_back}之间有更多的代码,则这很重要。"destroys tmp, after it's been moved from"。 - Andre Kostur
@AndreKostur 我并不是想暗示 tmp 被移动和 tmp 被销毁之间存在着因果关系;我是想解释为什么在 OP 的演示中第一个析构函数输出了空字符串,并描述了 tmp 在被销毁时的状态。但我看到这可能会引起困惑,所以进行了澄清。 - T.C.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接