析构函数会自动调用吗?

15
我的问题很简单,但我无法在任何地方找到答案。
如果我有这样的一个类
class A {
    vector<int> data;
}
A 的实例被销毁时,data 会被正确销毁吗?还是我需要编写一个调用 data 析构函数的 A 析构函数来确保其被正确销毁?基本上,我担心当 A 实例被销毁时,vector 的动态内存不会被释放。我怀疑答案是data将被正确释放,但我不想以错误的方式发现自己是错的。
此外,如果 A 是一个结构体,当局部实例 A 超出范围时,data 的析构函数会被调用吗?

2
class A的声明后面缺少一个分号(实际上这不算是一个声明,因为它缺少了……好吧)。 - Matthieu M.
3个回答

15

是的,data会自动销毁,您不需要做任何事情来实现它。 vector将处理其分配的动态内存的清理。当A的实例被销毁时,向量的析构函数将自动调用。

无论Aclass还是struct,行为都没有区别。


15
为了明确一点,这里的“vector将处理由它分配的动态内存清理”,指的是由vector分配的内存,而不是针对vector本身的内存清理。如果你在vector中存储了动态分配的对象,那么你有责任相应地使用delete进行删除。 - netcoder
@netcoder 的评论有些误导性。你可以在一个向量中存储指向动态分配对象的指针,但我认为你不能将动态分配的“对象”本身存储在向量中。如果你声明了一个 ClassA 类名的 vector<ClassA>,那么 vector 将负责销毁它所持有的 ClassA 对象。当然,如果你的 ClassA 对象持有指向其他对象的指针,那么删除它们的责任应该由 ClassA 来承担,而不是 vector 的责任,但这是另一回事了。 - Gab是好人

4

不需要,数据成员的析构函数总是会被调用。

显式的析构函数对于手动内存管理很有用。

struct a{
    int* ip;
    a() 
    : ip(new int(5)) 
    { }

    ~a() { delete ip; }
};

话虽如此,通常应使用RAII容器(如智能指针),因此我个人很少编写dtors。

其中一个例外是将基类的dtor声明为虚拟的。

struct base {
     virtual ~base() {}
};
struct child : public base {
    //base and child destructor automatically called 
}

1
遵循良好的RAII原则是值得赞赏的。当人们按照Stroustrup、Sutter、Meyers和其他现代C++思想家所建议的方式编写代码时,手动编写析构函数的需求应该越来越少。 - stinky472

1
如果您没有定义默认析构函数,编译器会自动创建一个。通常情况下,除非您有指针数据成员指向的内存是“拥有”的,或者您正在设计可被其他类派生的类,否则您不需要创建自己的析构函数,此时您至少要声明一个空的虚拟析构函数。
在所有情况下,无论是您自己的析构函数还是编译器创建的默认析构函数,当前类的非静态数据成员以及任何基类的析构函数都会在析构函数结束之前被调用,并且在析构函数本身返回之前被调用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接