【问题标题】:Calling the destructor in C++ does not destroy an object manually [duplicate]在 C++ 中调用析构函数不会手动销毁对象[重复]
【发布时间】:2018-11-24 16:22:30
【问题描述】:

我想在 C++ 中显式调用对象的析构函数来销毁该对象。

这只是一个简单的程序,用于试验编程语言的特性。我有一个将内部数据成员设置为 1 的默认构造函数,以及将内部数据成员设置为参数的重载构造函数,以及一个显示刚刚销毁对象的内部数据成员的析构函数。还有一个打印内部数据成员的函数。

#include <iostream>
using std::cout;
using std::endl;

class myClass {
  public:
   myClass()
   {
     i = 1;
     cout << "default ";
     cout << "constructor called with " << this->i << endl;
   }

   myClass(int i)
   {
     this->i = i;
     cout << "constructor called with " << this->i << endl;
   }

   ~myClass()
   {
     cout << "object " << i << " destroyed!" << endl;
   }

   void printData()
   {
     cout << "object's data is " << i << endl;
   }
  private:
   int i;  // private data member
};

int main() {
  myClass a;
  myClass b;
  myClass c(8);

  a.printData();
  b.printData();
  c.printData();

  /* I want to explicitly destroy object b. */
  b.~myClass();
  b.printData();

  /* all the destructors get called when the objects go out of scope */

  return 0;
}

我的推理是这样的:我认为析构函数导致对象被销毁,所以它不再存在于内存中。在我显式调用析构函数之后,我应该不再能够再次使用该对象,因为它已被销毁。但是,我可以调用对象的函数并打印内部数据成员的值。手动调用析构函数是否无法销毁对象?这里发生了什么? 输出:

default constructor called with 1
default constructor called with 1
constructor called with 8
object's data is 1
object's data is 1
object's data is 8
object 1 destroyed!
object's data is 1
object 8 destroyed!
object 1 destroyed!
object 1 destroyed!

调用析构函数会破坏对象,还是调用析构函数是破坏对象的结果?

【问题讨论】:

  • “请注意,直接为普通对象(例如局部变量)调用析构函数会在作用域结束时再次调用析构函数时调用未定义的行为。”来自:en.cppreference.com/w/cpp/language/destructor所以基本上不要这样做。
  • 您可以安全地手动调用析构函数的唯一时间是使用placement-new 构造对象时,在您的任何示例中都不是这种情况。如果您想要确定性控制对象何时被销毁,请将其放在您控制的范围内,或使用new/delete(或智能包装器)。但无论哪种方式,一旦一个对象被破坏,访问它的成员就不再安全了。所以在调用~myClass() 之后调用printData()未定义的行为
  • 调用析构函数不会释放内存。此外,即使确实如此,仅仅因为您释放了内存,它也不一定会消失。它可能会流连忘返。
  • 调用析构函数是销毁对象,还是调用析构函数是销毁对象的结果?
  • 手动调用析构函数不会销毁/释放对象。你应该使用删除。 delete b; 在你的情况下。您可能不想手动调用 d'tor,请考虑重新构建您的对象结构以避免这种情况。

标签: c++ oop destructor


【解决方案1】:

在我显式调用析构函数后,我应该不能再使用那个对象了,因为它已经被销毁了

没错。只是它是 C++,而不是像“当你做坏事时你会被警告”那样的“你不再能够”,它更像是“你可能会在未来的任何随机点被击中脚,而不会发出警告,如果你做坏事”(又名“未定义的行为”)。

在您的特定示例中,您破坏了对象,并且它在逻辑上不再存在。内存可能仍然被分配甚至包含一些旧数据。但是,尝试访问它是未定义的行为。它可能对您的编译器、编译器标志、源代码、操作系统和月相的特定组合“起作用”,以后可能会有所不同,从技术上讲,它甚至可能wipe your hard drive

此外,当您在局部变量中声明对象时,它会在第二次超出范围时自动销毁。这也是未定义的行为,但您的程序的行为已经完全未定义并不重要。

您可以尝试使用 Valgrind、AddressSanitizer 或 UndefinedBehaviorSanitizer 等动态分析来捕获此类内容,但它们不提供任何保证。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-12-31
    • 2010-11-05
    • 2014-05-12
    • 2011-05-24
    • 2016-11-10
    • 2021-07-04
    • 2018-01-02
    • 1970-01-01
    相关资源
    最近更新 更多