析构函数意外调用

Destructor called unexpectedly

提问人:Jabberwocky 提问时间:11/10/2023 更新时间:11/10/2023 访问量:130

问:

为什么这个简单代码中的析构函数被调用了两次?~TestClass()

#include <memory>
#include <iostream>
#include <vector>

class TestClass
{
  int m_val;

public:
  TestClass(int val);
  ~TestClass();
};

TestClass::TestClass(int val) : m_val(val)
{
  std::cout << this << " TestClass() " << m_val << "\n";
}

TestClass::~TestClass()
{
  std::cout << this << " ~TestClass() " << m_val << "\n";
  m_val = -1;
}

int main()
{
  auto x = std::make_unique<TestClass>(2);

  auto y = *x;  // <<<< this triggers it
}

输出

000001E66C0B5980 TestClass() 2
00000057FDD9FAB4 ~TestClass() 2   // why is the destructor called here?
000001E66C0B5980 ~TestClass() 2
C++ 智能指针 unique-ptr

评论

8赞 HolyBlackCat 11/10/2023
因为你有两个对象。你没有看到第二个构造函数调用,因为你没有检测复制构造函数(还有移动构造函数,但添加自定义复制构造函数将删除它,因此检测复制构造函数足以不遗漏任何对象)。
1赞 molbdnilo 11/10/2023
有两个实例;由 和 创建的那个。make_uniquey
2赞 463035818_is_not_an_ai 11/10/2023
你期望做什么?auto y = *x;
1赞 Fareanor 11/10/2023
y是 so then 被销毁并紧随其后的副本。*xy*x
2赞 user12002570 11/11/2023
@Red.Wave:另外,你似乎错过了重点。这是为重现stackoveflow上的特定问题而编写的,而不是为了解决它可能遇到的任何附加问题。一个最小的可重现示例是仅出于此类目的而创建,而不是审查代码以使其更好。TestClass

答:

1赞 user12002570 11/10/2023 #1

auto y = *x;<<<<这会触发它

以上是复制初始化,将使用类的复制构造函数。您看到的额外析构函数调用对应于此对象。您还可以通过向类中添加复制 ctor 来验证这一点,您会注意到该复制 ctor 用于使用 .yy*x

class TestClass
{
  int m_val;

public:
  TestClass(int val);
  ~TestClass();
   //added this copy ctor
  TestClass(const TestClass &p): m_val(p.m_val)
//-------------------------------^^^^^^^^^^^^^^--->use member initializer list
  {
      std::cout << this << " copy ctor " << m_val << "\n";
  }
};
//other code as before

评论

0赞 Red.Wave 11/11/2023
TestClass z {3}; z=y;和繁荣。你又失败了。 永远不会被破坏。3
0赞 user12002570 11/11/2023
@Red.Wave 问题不在于任何违规行为。这是关于为什么没有 dtor 调用。代码中的任何逻辑错误都不是我的责任来解决的。
0赞 Red.Wave 11/11/2023
很明显,您也需要学习 RAII。您的解决方案违反了规则 0/3/5;简而言之,这是错误的。答案应该提供关于问题根源的足够信息,而你的答案却没有。因为你自己不知道真正的问题。讨论结束。
0赞 user12002570 11/11/2023
@Red.Wave:不,解决世界上所有的问题或别人的代码不是我的责任。他们对自己的代码负全部责任。我不为别人的错误负责。我只指出问题中具体提出的问题,这就是为什么没有 dtor 调用。你不能把你的错误归咎于我。您最多可以建议链接到 OP 的三法则
0赞 Red.Wave 11/11/2023
您有责任不传播错误信息,而是提及正确答案。你当然不能提到你还没有掌握的东西;那是有人纠正你的时候。