c++ 移动构造函数不调用析构函数?

busg9geu  于 2023-04-13  发布在  其他
关注(0)|答案(2)|浏览(177)

我的理解是,析构函数是在调用move构造函数之后在输入上调用的。我决定在代码中测试一下(见底部),但得到的结果与我预期的不同。我使用std::unique_ptr得到了相同的结果。

预期:

1
2
bar constructed
foo destructed //due to move
3
i'm foo
4
[Error?]

实际:

1
2
bar constructed
3
i'm foo
4
i'm foo
5
foo destructed
foo destructed

验证码:

#include <iostream>

class Foo
{
public:
  ~Foo()
  {
    std::cout << "foo deconstructed" << std::endl;
  }
  void speak()
  {
    std::cout << "i'm foo" << std::endl;
  }
};

class Bar
{
public:
  Bar(Foo&& foo) : foo_(std::move(foo))
  {
    std::cout << "bar constructed" << std::endl;
  }
  Foo foo_;
};

int main()
{
  std::cout << "1" << std::endl;
  Foo foo;
  std::cout << "2" << std::endl;
  Bar bar(std::move(foo));
  std::cout << "3" << std::endl;
  bar.foo_.speak();
  std::cout << "4" << std::endl;
  foo.speak();
  std::cout << "5" << std::endl;
  return 0;
}
n9vozmp4

n9vozmp41#

我的理解是,析构函数是在调用move构造函数之后对输入调用的
你的理解是不正确的。当调用析构函数时,没有任何关于move语义或C++11的变化。这里没有任何变化-在本例中,foo的析构函数在main的末尾被调用。
您的困惑可能源于这样一个事实,即在许多情况下,析构函数似乎是在移动构造函数之后立即调用的。
例如,如果你要创建一个带有右值的BarBar bar(Foo{});Foo的析构函数将在Bar的移动构造函数之后运行。这不是因为有移动构造函数-而是因为临时Foo对象的生存期已经结束。

gtlvzcf8

gtlvzcf82#

析构函数在对象的生存期结束时被调用-对于自动存储持续时间对象,如foo,当它们超出范围时会发生这种情况。对于静态存储持续时间对象,当程序退出时会发生这种情况。对于临时对象,这种情况也会发生
1.在创建它们的语句的末尾-在Foo foo = Foo();中,假设没有复制省略,则Foo()创建的临时对象将被销毁。
1.当这个临时对象绑定到的引用被销毁时-在{const Foo& foo = Foo(); doStuff();}中,临时对象在作用域结束时被销毁(})。
这些条件都与移动构造函数无关。虽然没有强制要求,但移动构造函数通常会使被移出的对象保持有效状态。

相关问题