为一个类同时拥有析构函数和重载delete
的目的究竟是什么?
在哪种情况下应该同时使用两者?
答案 0 :(得分:5)
分配具有new
表达式的对象时,如:
X *x = new X();
它基本上做了两件事:它分配一些内存,然后在该内存中创建一个对象,大致相当于:
void *temp = operator new(sizeof(X));
X *x = new(temp) X;
第一个只分配一块原始内存。第二个只占用原始内存块,并在其中创建一个对象。
删除对象时大致相反:
delete x;
...大致等同于:
x->~X();
operator delete(static_cast<void *>(x));
因此,operator new和operator delete 只是处理分配和释放原始内存。构造函数和析构函数只是处理创建和销毁已经分配的内存中的对象。在析构函数运行以销毁某些内存中的对象之后,operator delete
用于释放内存本身。
默认情况下,有一对全局operator new
和operator delete
用于分配所有类型的对象。如果需要,您可以替换它们。您还可以为特定类提供operator new
和operator delete
(作为静态成员函数 1 )。在这种情况下,这些函数将仅用于管理该类对象的内存。这对于像极小的类这样的东西特别有用,并且你希望分配这个类的大量对象。许多内存管理器在处理极大数量的极小项时效率不高,因此在这种情况下重载可以提高(减少)内存使用量。
还有operator new[]
和operator delete[]
,在/分配/释放对象数组时使用。 operator new[]
只传递了一些要分配的字节,而operator delete
只是将一块原始内存传递给free。如果你决定重载这些,你可能会认为它们主要用于较大的内存块并进行适当的优化,但这是与非阵列版本的唯一区别。
作为一项规则,我会避免使用new
分配数组(永远),使这些完全无关。不,如果您创建类似std::vector<T>
之类的东西,它们也不会被分配器使用。好吧,我想如果你不介意彻底滥用系统,你可以创建一个分配器,用于使用std::vector
来管理分配的new char[size]
,其中如果它会使用其中一种,但我发现很难想象任何人都会这样做。也许曾经有一次C ++没有得到很好的理解,但现在它会像任何体面的代码库中的拇指一样突出。
1.一个小的奇怪之处:编译器“知道”它们必须始终是静态的,所以即使你在声明/定义它们时不使用static
关键字,它们也会是静态的。
功能
答案 1 :(得分:3)
一旦你意识到构造函数/析构函数和new / delete对用于正交目的,答案就会变得清晰:
new
和delete
让您的类控制获取和释放分配给类本身实例的内存的过程。同样重要的是要认识到new
和delete
的调用包含构造函数和析构函数的调用:new
在构造函数之前发生,而delete
发生在之后析构函数。虽然析构函数可能会将对象的内容视为“实时”,但运算符delete
必须将其视为“死”;特别是,试图引用任何成员或从delete
调用该类的任何成员函数是未定义的。
现在答案应该是明确的:你实施一个或另一个,或两者兼而有之,取决于你的程序希望控制什么。
答案 2 :(得分:1)
根据我的理解,析构函数旨在实现特定于类的行为,例如释放已分配的资源等,而重载delete
运算符则用于自定义内存管理,这不是特定于类的,或者是不仅仅针对一个班级as described here。通常,没有必要重载new
和delete
。
答案 3 :(得分:0)
析构函数用于销毁类(对象)的实例,无论它是作为自动变量在堆栈上分配,还是在具有运算符new
的堆上。
当代码使用运算符new
和delete
时,重载的new
和delete
将仅用于分配内存。
请注意,new
和delete
是静态的,可以使用void(非结构化)内存。他们无法通过(隐式或显式)this
访问该类的成员。您可以将此内存转换为您的对象并初始化/重置它,但它们并不适合用于此目的。