为什么 C++对象有默认的析构函数吗?
例如,当我没有声明构造函数时,编译器将为我提供一个默认构造函数,该构造函数没有参数,也没有定义(空主体),因此将不执行任何操作。
因此,例如,如果我完成了一个对象,默认析构函数不会重新分配该对象使用的(释放)内存吗?如果没有,我们为什么要得到它?
而且,也许同样的问题也适用于默认构造函数。如果它什么都不做,为什么默认为我们创建它?
When I don't declare a constructor for example, the compiler will provide me with a default constructor that will have no arguments and no definition (empty body), and thus, will take no action.
So, if I'm finished with an object for example, wouldn't the default destructor reallocate (free) memory used by the object? If it doesn't, why are we getting it?
And, maybe the same question applies to the default constructor. If it does nothing, why is it created for us by default?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
说编译器生成的默认构造函数不执行任何操作是错误的。它相当于具有空主体和空初始值设定项列表的用户定义构造函数,但这并不意味着它不执行任何操作。它的作用如下:
而且,仅当类不是多态的、没有基类并且没有需要构造的成员时,编译器生成的默认构造函数才会执行任何操作。但即便如此,出于其他答案中解释的原因,有时也需要默认构造函数。
析构函数也是如此 - 它调用基类的析构函数和具有它们的所有成员的析构函数,因此在一般情况下编译器生成的析构函数不执行任何操作。
但内存分配实际上与此无关。内存在调用构造函数之前分配,并且仅在最后一个析构函数完成后才释放。
It's wrong to say that a compiler-generated default constructor takes no action. It is equivalent to a user-defined constructor with an empty body and an empty initializer list, but that doesn't mean it takes no action. Here is what it does:
And only if a class is not polymorphic, has no base class and has no members that require construction, then a compiler-generated default constructor does nothing. But even then a default constructor is sometimes necessary for the reasons explained in other answers.
The same goes for the destructor - it calls base class'es destructor and destructors of all members which have them, so it isn't true in general case that a compiler-generated destructor does nothing.
But memory allocation really has nothing to do with this. The memory is allocated before the constructor is called, and it is freed only after the last destructor has finished.
因为如果您没有任何(公共可访问的)构造函数或析构函数,则无法实例化该类的对象。请考虑:
如果您没有显式声明任何构造函数或析构函数,则编译器必须提供一个以允许创建对象。
Because if you don't have any (publiclly-accessible) constructors or destructors, then an object of the class cannot be instantiated. Consider:
If you don't explicitly declare any constructors or destructors, the compiler must provide one to allow creation of objects.
使用智能指针时,默认析构函数(请参阅 Sergey 的回答)对于避免内存泄漏至关重要。这是一个示例:
这里的输出显示仅
foo2
发生泄漏:When using smart pointers, the default destructor (see Sergey's answer) can be critical to avoid memory leaks. Here an example:
Here the output, showing that a leak occurs only for
foo2
:默认析构函数不会执行任何操作(就像默认构造函数一样)。
如果您的析构函数实际上需要执行某些操作(例如:释放一些资源),您需要自己定义一个。
请注意,通常您应该遵循三规则:如果您程序需要在其析构函数中执行某些操作(例如:释放资源),您还应该提供复制构造函数和赋值运算符; C++ 还提供了它们的默认版本(同样,它不会执行任何操作)。
当您处理不需要执行任何操作的简单类时,默认构造函数/析构函数/赋值运算符/复制构造函数非常有用。一个特殊情况是 POD:它们(C++0x 之前的版本)甚至不能有显式的构造函数或析构函数。
Default destructor won't do anything (just like a default constructor).
You'll need to define one yourself, if your destructor actually needs to do something (eg: freeing some resources).
Note that usually you should follow the rule of three: if your program needs to do something in its destructor (eg: freeing resources) you should also provide a copy constructor and an assignment operator; C++ also provides default versions of them (which, again, won't do anything).
Default constructor/destructor/assignment operator/copy constructor are useful when you're handling simple classes where you don't need to do anything. A special case are POD: they (prior to C++0x) even cannot have explicit constructors or destructor.
默认构造函数和析构函数只是一种商品,如果您不需要对类进行任何特殊操作,则无需手动编写空版本。这对于其他 OO 语言来说很常见,例如在 Java 中,如果成员的零初始化就足够了,则不需要提供构造函数。同时它也是与C向后兼容的要求。如果你在C中有一个struct,它不会有构造函数或析构函数(C没有这些概念),能够处理C++ 中的代码必须是有效的代码。
另一种选择是在语言中声明类可以没有构造函数或析构函数,但是整个语言规范必须处理这样的事实:某些类型可能具有构造函数和析构函数,而其他类型则没有,这将使语言更复杂,更难指定。虽然拥有隐式定义的版本不会改变行为并简化规范。
在这个级别,它就像应用于基类中的方法的术语“overrider”。在基类中,它不会覆盖任何东西,没有什么可以覆盖的!然而,该语言明确指出在基类中声明的虚拟非纯方法是重写器。这使得规范可以简单地说,当通过指针或引用调用方法时,将调用最终重写器,而无需添加 extre *或基本方法实现(如果该特定的重写器不存在)该特定层次结构中的方法。
The default constructor and destructors are just a commodity in case you do not need anything special done with your class you do not need to write an empty version manually. This is common to other OO languages, for example in Java you do not need to provide a constructor if zero initialization of the members suffices. At the same time it is a requirement for backwards compatibility with C. If you have a
struct
in C, it will not have constructor or destructor (C does not have those concepts), to be able to handle that code in C++ that has to be valid code.Another option would have been declaring in the language that a class could have no constructor or destructor, but then the whole language spec would have to deal with the fact that some types might have constructors and destructors while others don't, and that will make the language more complex and harder to specify. While having that implicitly defined versions does not change the behavior and eases the specification.
At this level it is like the term overrider being applied to the method in the base class. In the base class, it does not override anything, there is nothing to override! And yet the language explicitly states that a virtual non-pure method declared in a base is an overrider. This enables the spec to simply say that the final overrider will be called when the method is called through a pointer or reference without having to add an extre *or the base method implementation if no overrider exists for that particular method in that particular hierarchy.
简而言之,在 C++ 中,每个对象都需要一个构造函数和一个析构函数,即使它们不执行任何操作。因此,编译器在后台为您创建它们满足了这一要求。
更长的答案是构造函数负责类成员的初始化。默认构造函数对所有成员进行默认初始化。 (这对于 POD 类型没有任何意义,但其他类会调用其默认构造函数。)
The short answer is that in C++ every object needs a constructor and a destructor, even if they don't do anything. So the compiler creating them for you in the background satisfies this requirement.
A longer answer is that the constructors are responsible for initialization of members of the class. The default constructor does default initialization of all of the members. (That doesn't mean anything for POD types, but other classes get their default constructors called.)
默认析构函数无法知道您的类“拥有”哪些内存来释放它。
至于默认构造函数部分,我将引用关于此的 Wikipedia 文章...
A default destructor would have no way of knowing what memory your class "owns" to be able to free it.
As to the default constructor part, I will quote the Wikipedia article on this one...