C++ 构造函数和析构函数

C++ 构造函数和析构函数,c++,constructor,eclipse-cdt,destructor,C++,Constructor,Eclipse Cdt,Destructor,我有下面的代码,正如我所知,在使用类构造函数的程序结束时,如果创建了某些对象,它们就会被销毁。由此判断,在执行结束时,我应该按照特定的顺序打印一些~B和~D,但在我运行代码时不会发生这种情况。为什么 #include<iostream> #include<stdlib.h> using namespace std; class B{ public: B(){cout<<"B()";} virtual void print(){cout<

我有下面的代码,正如我所知,在使用类构造函数的程序结束时,如果创建了某些对象,它们就会被销毁。由此判断,在执行结束时,我应该按照特定的顺序打印一些~B和~D,但在我运行代码时不会发生这种情况。为什么

#include<iostream>
#include<stdlib.h>
using namespace std;

class B{
public:
    B(){cout<<"B()";}
    virtual void print(){cout<<"b";}
    ~B(){cout<<"~B()";}
};

class D:public B{
public:
    D(){cout<<"D()";}
    void print(){B::print()
    ;cout<<"d";}
    ~D(){cout<<"~D()";}
    };

void testI(){
    B* b[]={new B(),new D()};
    b[1]->print();
    B&c=*b[1];
    c.print();
}



int main(){
    testI();
return 0;
}

因为您使用动态分配。为此,你有责任销毁你分配的东西

在此处阅读有关新建和删除的信息:
因为您使用动态分配。为此,你有责任销毁你分配的东西

在此处阅读有关新建和删除的信息:

您正在使用new创建对象,这意味着它们是在堆上而不是在堆栈上分配的,因此您可以删除它们

B * b = new B();
后来

delete b;
编辑:

对于阵列使用:

delete[] b; //if b is a pointer to an array of B's

您正在使用new创建对象,这意味着它们是在堆上而不是在堆栈上分配的,因此您可以删除它们

B * b = new B();
后来

delete b;
编辑:

对于阵列使用:

delete[] b; //if b is a pointer to an array of B's

您正在使用new来分配动态内存,而不删除对象。虽然您可以通过添加delete语句来解决这个问题,但随着代码变得越来越复杂,您会发现手动内存管理会变得笨拙且容易出错

使用自动内存管理类(如std::unique_ptr和std::shared_ptr)以及容器类(如std::vector)会更好


您正在使用new来分配动态内存,而不删除对象。虽然您可以通过添加delete语句来解决这个问题,但随着代码变得越来越复杂,您会发现手动内存管理会变得笨拙且容易出错

使用自动内存管理类(如std::unique_ptr和std::shared_ptr)以及容器类(如std::vector)会更好

在规范中:

3.6.1.5-main中的返回语句具有离开main函数的效果 销毁具有自动存储持续时间的任何对象

因此,在您的程序中,您创建了几个变量。从main返回时,只有具有自动存储持续时间的才会被销毁。具有动态存储持续时间的则不适用。对于具有动态存储持续时间的变量,必须显式调用delete

这里有一个小例子。在析构函数中放置断点并检查m_name值

#include <iostream>
#include <string>

class A
{
public:
    A(const std::string &name):m_name(name){}

    ~A()
    {
        std::cout<<"deleting "<<m_name<<std::endl;
    }

private:
    std::string m_name;
};

A a("Variable at namespace scope");

int main()
{
    A a0("Automatic storage"); 
    A *a1 = new A("Dynamic storage 1"); 
    A *a2 = new A("Dynamic storage 2"); 
    delete a2;
    static A a3("Static storage");

    return 0;
}
在规范中:

3.6.1.5-main中的返回语句具有离开main函数的效果 销毁具有自动存储持续时间的任何对象

因此,在您的程序中,您创建了几个变量。从main返回时,只有具有自动存储持续时间的才会被销毁。具有动态存储持续时间的则不适用。对于具有动态存储持续时间的变量,必须显式调用delete

这里有一个小例子。在析构函数中放置断点并检查m_name值

#include <iostream>
#include <string>

class A
{
public:
    A(const std::string &name):m_name(name){}

    ~A()
    {
        std::cout<<"deleting "<<m_name<<std::endl;
    }

private:
    std::string m_name;
};

A a("Variable at namespace scope");

int main()
{
    A a0("Automatic storage"); 
    A *a1 = new A("Dynamic storage 1"); 
    A *a2 = new A("Dynamic storage 2"); 
    delete a2;
    static A a3("Static storage");

    return 0;
}

其中是delete,而B需要一个虚拟析构函数?因为您正在使用new创建对象,而不是调用delete。尝试int main{B;}其中是delete,而B需要一个虚拟析构函数?因为您正在使用new创建对象,而不是调用delete。尝试int main{B;}我忘记了堆。谢谢。我忘记了堆。谢谢。当您从main返回或调用exit时,具有静态生存期的对象也将被销毁。这不是本文的目的,但您是对的,最好也添加。谢谢。不是真的,但这也是一个很好的观点。我实际上是在考虑命名空间范围内的变量。@JamesKanze:edited。我希望这是你的意思。谢谢当您从main或callexit返回时,具有静态生存期的对象也将被销毁。这不是本文的目的,但您是对的,最好也添加。谢谢。不是真的,但这也是一个很好的观点。我实际上是在考虑命名空间范围内的变量。@JamesKanze:edited。我希望这是你的意思。谢谢