析构函数vs重载删除

时间:2014-09-17 13:18:56

标签: c++ overloading destructor

为一个类同时拥有析构函数和重载delete的目的究竟是什么?

在哪种情况下应该同时使用两者?

4 个答案:

答案 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 newoperator delete用于分配所有类型的对象。如果需要,您可以替换它们。您还可以为特定类提供operator newoperator 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对用于正交目的,答案就会变得清晰:

  • 构造函数和析构函数允许您的类控制获取和释放类所拥有的资源的过程。这些不包括对象本身的内存。
  • 运算符newdelete让您的类控制获取和释放分配给类本身实例的内存的过程。

同样重要的是要认识到newdelete的调用包含构造函数和析构函数的调用:new在构造函数之前发生,而delete发生在之后析构函数。虽然析构函数可能会将对象的内容视为“实时”,但运算符delete必须将其视为“死”;特别是,试图引用任何成员或从delete调用该类的任何成员函数是未定义的。

现在答案应该是明确的:你实施一个或另一个,或两者兼而有之,取决于你的程序希望控制什么。

答案 2 :(得分:1)

根据我的理解,析构函数旨在实现特定于类的行为,例如释放已分配的资源等,而重载delete运算符则用于自定义内存管理,这不是特定于类的,或者是不仅仅针对一个班级as described here。通常,没有必要重载newdelete

答案 3 :(得分:0)

析构函数用于销毁类(对象)的实例,无论它是作为自动变量在堆栈上分配,还是在具有运算符new的堆上。

当代码使用运算符newdelete时,重载的newdelete将仅用于分配内存。

请注意,newdelete是静态的,可以使用void(非结构化)内存。他们无法通过(隐式或显式)this访问该类的成员。您可以将此内存转换为您的对象并初始化/重置它,但它们并不适合用于此目的。