为什么不用C ++调用Destructor?

时间:2017-01-26 09:59:12

标签: c++ constructor destructor

我研究@Configuration public class MailConfig { @Bean @ConditionalOnProperty(name="spring.mail.host", havingValue="foo", matchIfMissing=true) public MailSender mockMailSender() { return new MockMailSender(); } @Bean @ConditionalOnProperty(name="spring.mail.host") public MailSender smtpMailSender(**JavaMailSender javaMailSender**) { SmtpMailSender mailSender = new SmtpMailSender(); mailSender.setJavaMailSender(javaMailSender); return mailSender; } } 概念。我在构造函数和Destractor概念中感到困惑。编译器在退出程序时将隐式调用析构函数。但在我的程序中,只有构造函数调用。

C++

输出:

#include <iostream>
using namespace std;

class A
{
        int i;
public:
        A()
        {
                cout<<"Constructor call"<<endl;
        }
        ~A()
        {
                cout<<"Destructtor call"<<endl;
        }
};

int main()
{
        A *a = new A();
}

所以,我有疑问:为什么析构函数在退出程序时不会被编译器隐式调用?

6 个答案:

答案 0 :(得分:7)

  

为什么析构函数在退出程序时不会被编译器隐式调用?

因为动态分配的对象不会自动销毁。这就是指定语言的方式。跟踪动态对象的破坏需要运行时/内存开销。

解决方案:不要泄漏动态分配的对象。

答案 1 :(得分:4)

C ++中有两种“变量生命周期”类型。动态和自动。

自动就像:

$request->request->get("data-name"); 

此处,void foo() { int i; // automatic storage } // destroys i 将在离开范围时被破坏(i返回后)。您可以通过使对象具有自动生命周期来自行检查:

foo

你会看到构造函数和析构函数都会被调用。

第二种形式是动态分配的内存。您可以使用int main() { A a; // calls A's constructor and allocates memory. } //calls A's destructor and frees the memory used. (与您一样)动态分配内存,并使用new释放内存。编译器不会为您执行此操作。 这意味着,要破坏对象,您必须自己明确调用delete

delete

如果你没有打电话给int main() { A* a = new A(); delete a; // calls A's destructor and frees the memory used. } (就像你的代码一样),那么当程序离开delete时,指针main就会被销毁,现在我们有一块内存,无法达到因此,没有人可以清理(a),这意味着你是leaking memory

但是,现代操作系统会在程序结束时自动回收程序使用的所有内存,因此此时无关紧要。这意味着您的析构函数不会像您刚刚目睹的那样被调用。

动态分配的内存允许你做一些漂亮的技巧,比如控制对象的生命周期到你想用delete自己明确销毁它们的点。使用deletenew的问题在于忘记单个delete很容易,并且您的程序已经泄漏内存,这就是为什么建议远离这种分配方式

如果由于某种原因你绝对需要动态生命周期,那么使用像delete这样的智能指针,它会在它超出范围时为你调用std::unique_ptrnew

答案 2 :(得分:3)

使用import java.util.ArrayList; import java.util.Map; import com.my.ContextDroolsObject; dialect 'java' rule 'Soccer Image Theme' salience 100 when s : ContextDroolsObject() objectsm : Map() from s.objects imageThemesList : ArrayList() from outputsm.imageThemes then System.out.println("-----------------------soccer"); end 动态创建对象。仅当使用new删除对象时才会调用析构函数。

为了防止内存泄漏,您可以/应该使用delete等智能指针。

在任何情况下,当进程结束时,内存本身当然会被释放。

答案 3 :(得分:2)

从不在代码中调用析构函数,因为对象永远不会被销毁。

您动态分配A对象,并且永远不会释放它。将delete a;添加到main(),您将看到正在运行的析构函数:

int main()
{
    A *a = new A();
    delete a;

    return 0;
}

答案 4 :(得分:1)

在main函数中,您创建一个指针变量,您必须在主函数结束时通过delete a将其删除。

答案 5 :(得分:0)

因为你有内存泄漏。您动态创建了一个new的对象,承诺您将管理对象的生命周期并稍后使用delete进行清理。然后你违背了这个承诺。

如果您以通常的方式创建对象:

A a;

然后它将自动销毁。