缺少析构函数声明
missing destructor declaration
如果我忘记在C++类中声明destrucor,有人能告诉我对象的内存会发生什么吗?我的意思是,它是被释放还是导致内存泄漏?示例或演示将不胜感激。
提前谢谢。
为任何非平凡类定义析构函数通常被认为是一种很好的做法(请参阅三规则)。然而,在现代C++(即C++11以后)中,它不像过去那样必要了。
如果您的类不是从其他任何东西继承的,那么编译器提供的默认析构函数将正确地销毁任何直接成员(如变量和对象)。类似地,如果您的对象拥有任何被封装在智能指针中的堆分配对象,它们也将被安全地销毁。
如果您的对象通过原始指针拥有任何堆分配的数据,就会出现问题。隐式析构函数无法知道如何处理它们,因此您需要一个自定义析构函数来清除它们。例如:
class MyClass
{
int m_data1;
std::string m_data2;
std::shared_ptr<Widget> m_data3;
Widget *m_data4;
};
在上面的示例中,成员m_data1
、m_data2
和m_data3
都将在没有自定义析构函数的情况下被正确清除。但是,m_data4
指向的对象将不会自动清除。如果它是由MyClass
分配的,那么它通常会导致内存泄漏(除非它被其他东西释放)。
综上所述,继承在很大程度上改变了事物。如果你的类被其他任何东西继承,那么你可能应该总是给它一个虚拟析构函数。如果您的对象是通过指向继承类的指针删除的,而该类没有虚拟析构函数,则永远不会调用子类的析构函数。这可能会导致内存泄漏。
例如:
class Parent
{
public:
Widget m_data1;
}
class Child : public Parent
{
public:
Widget m_data2;
}
int main()
{
Parent *ptr = new Child;
delete ptr; // <-- clears-up Parent but not Child
}
在上面的例子中,ptr
是Parent
类型,所以delete
只知道对象的Parent
部分。这意味着只有m_data1
会被正确清除。如果没有虚拟析构函数,它就不知道对象的Child
部分,因此m_data2
将不会被正确清除(其析构函数永远不会被调用)。
如果未声明析构函数,编译器将生成析构函数。析构函数将调用对象所有成员的析构函数。只有当您使用原始内存(C文件、内存分配等)时,才会发生泄漏。
它取决于类的数据成员。如果类管理资源,那么它需要一个析构函数来释放它们(您还应该提供一个复制构造函数和赋值运算符,或者使类不可复制和不可赋值)。
如果类有内置的数据成员,或者管理自己资源的数据成员的话,那么隐式生成的析构函数就足够了。它将调用所有数据成员的析构函数。
- 如果在C++中不需要构造函数或析构函数,是否有必要显式声明它?
- 为什么 "=default" 析构函数与隐式声明的析构函数不同?
- 我们什么时候应该在 C++ 中将析构函数声明为 =DELETE
- 析构函数在 lambda 捕获说明符中声明的类实例上运行两次
- 为什么在声明析构函数时必须声明 copy & move 构造函数?
- 当声明了虚拟析构函数但没有实现时会发生什么情况
- 析构函数删除在 main 中声明的动态数组
- 显式声明派生类中所需的析构函数
- 缺少析构函数声明
- 结构sqlite3的sqlite3c++正向声明导致析构函数中删除时出现无效指针错误
- 为什么简单析构函数在使用基指针声明时不删除派生对象
- C++自动生成带有用户声明析构函数的移动构造函数
- 不稳定的声明行为:Rational.h:25:错误:在"&"标记之前预期的构造函数、析构函数或类型转换
- C++ - 如果在循环中声明对象,是否在循环结束时调用其析构函数
- 如何在不中断移动和复制构造函数的情况下声明虚拟析构函数
- 声明析构函数虚拟就足够了吗?
- 需要声明析构函数为默认值
- 自动生成带有声明析构函数的默认移动构造函数
- 如果声明析构函数,为什么此代码无法编译?
- 如何在SystemC中声明析构函数?