如何调用类的析构函数?

use*_*002 9 c++ destructor

我有一个简单的C++代码,但我不知道如何使用析构函数:

class date {

public:
    int day;
    date(int m)
    {
        day =m;
    }

    ~date(){
    cout << "I wish you have entered the year \n" << day;    
    }
};


int main()
{
  date ob2(12);
  ob2.~date();
  cout << ob2.day;
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

我的问题是,我应该在我的析构函数代码中写什么,在调用析构函数之后,它会删除day变量

Jam*_*lis 17

你很少需要明确地调用析构函数.相反,在销毁对象时会调用析构函数.

对于像ob2这样的对象是局部变量,当它超出范围时会被销毁:

int main() 
{ 
    date ob2(12); 

} // ob2.~date() is called here, automatically!
Run Code Online (Sandbox Code Playgroud)

如果使用动态分配对象new,则在使用时销毁对象时会调用其析构函数delete.如果您有一个静态对象,则在程序终止时调用其析构函数(如果程序正常终止).

除非你使用动态创建一些东西new,否则你不需要做任何明确的事情来清理它(例如,当它ob2被销毁时,它的所有成员变量都会day被破坏).如果你动态创建一些东西,你需要确保它在完成后被破坏; 最好的做法是使用所谓的"智能指针"来确保自动处理这种清理.


Kon*_*lph 13

您不需要显式调用析构函数.这在对象范围的末尾自动完成ob2,即在main函数结束时完成.

此外,由于对象具有自动存储,因此不必删除其存储.这也是在功能结束时自动完成的.

几乎从不需要手动调用析构函数(仅在低级库代码中),并且只有在以前使用new(当您使用指针时)获取内存时才需要手动删除内存(并且只需要有效操作).

由于人工内存管理是容易泄漏,现代C++代码尝试不使用newdelete明确的.当真的需要使用时new,则使用所谓的"智能指针"而不是常规指针.


Dav*_*eas 5

只有在非常特殊的情况下,您才需要直接调用析构函数。默认情况下,当您创建自动存储的变量并且它超出范围或动态分配的对象new被销毁时,系统将调用析构函数delete

struct test {
   test( int value ) : value( value ) {}
   ~test() { std::cout << "~test: " << value << std::endl; }
   int value;
};
int main()
{
   test t(1);
   test *d = new t(2);
   delete d;           // prints: ~test: 2
}                      // prints: ~test: 1 (t falls out of scope)
Run Code Online (Sandbox Code Playgroud)

为了完整起见,(通常不应使用)调用析构函数的语法类似于方法。析构函数运行后,内存不再是该类型的对象(应该作为原始内存处理):

int main()
{
   test t( 1 );
   t.~test();            // prints: ~test: 1
                         // after this instruction 't' is no longer a 'test' object
   new (&t) test(2);     // recreate a new test object in place
}                        // test falls out of scope, prints: ~test: 2
Run Code Online (Sandbox Code Playgroud)

注意:在 上调用析构函数后t,该内存位置不再是 a test,这就是通过放置 new重新创建对象的原因。


Mar*_*ius 5

您不应显式调用析构函数。

在堆栈上创建对象时(就像您所做的一样),您需要做的是:

int main()
{
  date ob2(12);
  // ob2.day holds 12
  return 0; // ob2's destructor will get called here, after which it's memory is freed
}
Run Code Online (Sandbox Code Playgroud)

当您在堆上创建对象时,在delete调用其析构函数并释放内存之前,您需要某种类:

int main()
{
  date* ob2 = new date(12);
  // ob2->day holds 12
  delete ob2; // ob2's destructor will get called here, after which it's memory is freed
  return 0;   // ob2 is invalid at this point.
}
Run Code Online (Sandbox Code Playgroud)

(在最后一个示例中未能调用delete会导致内存丢失。)

两种方式都有其优点和缺点。堆栈分配对象所占用的内存非常快,您不需要显式删除它,但是堆栈空间有限,您无法轻松,快速,干净地移动这些对象。

首选的方法是使用堆,但是在性能方面,分配速度很慢,您必须处理指针。但是,您对对象执行的操作具有更大的灵活性,可以更快地进一步处理指针,并且可以更好地控制对象的生命周期。

  • “堆是实现它的首选方式” –做*什么*?存放物体?因为那是错误的:在C ++中,堆栈绝对是首选的方法。 (2认同)
  • 对不起,但这是错误的。对于参数传递,使用 (const) 引用。对于返回值 - 只需复制。不会有什么不好的事情发生。参见例如 http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/ 库不应该需要堆分配的参数。这将是一个**非常**糟糕的库设计。堆栈分配没有任何快速和肮脏的地方。 (2认同)