c++中的垃圾收集/析构函数

garbage collection/destructors in C++

本文关键字:析构函数 c++      更新时间:2023-10-16

我是c++新手。据我所知,与java不同,c++没有自动垃圾处理,所以我们在类中为对象添加析构函数:

class A{
class A();
~class A(); // destructor
};

我很好奇当我们使用结构体时会发生什么。另外,如果不向类添加析构函数,会发生什么情况?内存是如何释放的?

c++中结构体和类之间的唯一区别是默认的访问控制——默认情况下,类的成员是私有的,而结构体的成员是公有的。如果你不定义自己的析构函数,编译器会给你一个默认的析构函数;当对象被销毁时,所有成员也被销毁。只有当任何类成员指向堆分配的内存时,才需要定义自己的析构函数。

适用于类的相同规则也适用于c++中的结构体,唯一的例外是默认访问级别,而不是其他。

如果不定义析构函数,编译器将为您定义默认析构函数。可用于类和结构。

默认构造函数调用基类的析构函数和所有具有它们的成员的析构函数。默认析构函数只是一种商品,如果你不需要对你的类做任何特别的事情,你不需要手动编写一个空版本(比如从堆中释放一个动态分配的对象,或者管理非自动成员)。

c++没有任何垃圾收集。这几乎是真的。析构函数是一个非常有用的工具,也用于收集垃圾。

类中有4个预定义的方法:默认构造函数、复制构造函数、赋值操作符的重载和析构函数。这意味着这些方法有一个默认版本:

  • 默认构造函数将调用所有类成员的默认构造函数。
  • 复制构造函数将所有类成员复制到另一个。赋值操作符就像一个特殊的复制构造函数。
  • 默认析构函数将调用所有类成员的析构函数。

当你定义:

class A {
private:
    int* a;
public:
    A() { a = new int(5); }
};

默认析构函数只会擦除指针在自身中分配的内存,而不会释放int(5)占用的内存。

因此我们需要定义一个特定的析构函数:
~A() { delete a; }

或者使用智能指针。

我认为比较Java和c++是一个很好的回答。在Java中,所有引用类型都存储在堆中,而所有原语都存储在堆栈中。这意味着,当原语超出作用域时,它们将被销毁;也就是说,当声明它们的方法返回时。另一方面,引用类型则不是这样。

在c++中,您可以控制哪个变量是动态存储(在堆中)还是自动存储(在堆栈中)。如果您使用new操作符创建了一个对象,它将一直留在堆中,直到您使用相应的delete释放该内存。如果您创建一个没有new操作符的变量(或对象),当对象超出作用域时,它的内存将被释放。

回答你关于构造函数和析构函数的问题:构造函数是一种总是在创建新对象时调用的方法。如果不指定任何构造函数,则暗示使用默认构造函数(不带参数)。当对象超出作用域时,或者使用delete操作符将其删除时(在使用new动态创建它的情况下),将调用析构函数。