C++ 如何不删除基类对象的副本?
我的问题是,当我使用继承类时,我的基类删除了2次(继承的副本也删除了)。是否有机会不复制基类?还是不删除呢C++ 如何不删除基类对象的副本?,c++,C++,我的问题是,当我使用继承类时,我的基类删除了2次(继承的副本也删除了)。是否有机会不复制基类?还是不删除呢 #include <iostream> using namespace std; class base { public: base() { cout << "*B"; } ~base() { cout << "~B"; } }; class restaurant : virtual public base {}; int main
#include <iostream>
using namespace std;
class base {
public:
base() { cout << "*B"; }
~base() { cout << "~B"; }
};
class restaurant : virtual public base {};
int main() {
base* d1 = new base;
restaurant restaurant;
delete d1;
return 0;
}
#包括
使用名称空间std;
阶级基础{
公众:
base(){cout您不是delete
ingrestaurant
,但是您也没有new
它;它是在自动存储(“堆栈”)中分配的,而不是在动态存储(“堆”)中分配的。自动存储中的对象在超出作用域时会调用其析构函数。这就是为什么在这种情况下仍会调用餐厅
析构函数的原因
如果你写过:
restaurant *restaurant = new restaurant;
您将看到您期望的行为。当然,如果调用new
而没有匹配的delete
,您将泄漏对象,因此不建议这样做。您没有delete
ingrestaurant
,但您也没有new
它;它是在自动存储(“堆栈”)中分配的,而不是动态存储(“堆”)。自动存储中的对象在超出范围时会调用其析构函数。这就是为什么在这种情况下仍会调用析构函数的原因
如果你写过:
restaurant *restaurant = new restaurant;
您将看到您期望的行为。当然,如果调用new
而没有匹配的delete
,您将泄漏对象,因此不建议这样做。输出是期望的输出。
我在你的主要功能代码中添加了注释
int main() {
//Create base class object and constructor will be called
//This object is allocated on heap
base* d1 = new base;
//Create derived class object
//first constructor of base and then derived (if defined) will be called
//This object is allocated on stack
restaurant restaurant;
//Free memory and Call destructor of base class object
delete d1;
return 0;
//After bracket, stack object will go out of scope and destructor will be called.
//First derived (if defined) class destructor and then base class destructor.
}
要获得预期的输出:*B*B~B
restaurant *restaurant = new restaurant;
但如果不删除它,则会在程序中产生内存泄漏。输出为预期输出。
我在你的主要功能代码中添加了注释
int main() {
//Create base class object and constructor will be called
//This object is allocated on heap
base* d1 = new base;
//Create derived class object
//first constructor of base and then derived (if defined) will be called
//This object is allocated on stack
restaurant restaurant;
//Free memory and Call destructor of base class object
delete d1;
return 0;
//After bracket, stack object will go out of scope and destructor will be called.
//First derived (if defined) class destructor and then base class destructor.
}
要获得预期的输出:*B*B~B
restaurant *restaurant = new restaurant;
但如果不删除它,则会在程序中产生内存泄漏。首先,具有自动存储的对象会在作用域的末尾自动删除。因此,声明餐厅餐厅;
将构造餐厅,但也会在主功能的末尾自动删除它
试试这个:
struct A {
A() { std::cout << "A()"; }
~A() { std::cout << "~A()"; }
};
struct B : A {
B() { std::cout << "B()"; }
~B() { std::cout << "~B()"; }
};
auto main() -> int {
B b;
} // b destroyed here
它的行为就像一个堆栈。首先,构造基类,然后构造派生类。然后,它首先销毁派生类,最后销毁基类
<>这个行为对于大多数C++习语来说是非常重要的。
考虑这一点:
struct A {
A() : arr(new int[3]{1, 2, 3}) {}
~A() { delete[] arr; }
int* arr = nullptr;
};
struct B : A {
B() {}
~B() {}
auto stuff() -> int {
return std::accumulate(arr, arr + 3, 0);
}
};
auto main() -> int {
B b;
return b.stuff(); // returns 1 + 2 + 3
}
如果没有首先执行构造函数A()
,会发生什么情况?数组将为null。这将很糟糕
还有…如果析构函数~A()
没有执行会发生什么?那将是内存泄漏。那将非常糟糕
构造函数和析构函数有保证的执行和定义良好的顺序。这就是为什么不必调用super()
和~super()
在你们所有的构造函数和析构函数中。因为你们可能会忘记调用它。析构函数和构造函数并不是你们想忘记调用的东西,否则仅仅使用C中的自由函数是没有好处的。首先,具有自动存储的对象会在作用域结束时自动删除。所以声明e> 餐厅餐厅;
将创建一个餐厅,但也将在主功能的末尾自动删除该餐厅
试试这个:
struct A {
A() { std::cout << "A()"; }
~A() { std::cout << "~A()"; }
};
struct B : A {
B() { std::cout << "B()"; }
~B() { std::cout << "~B()"; }
};
auto main() -> int {
B b;
} // b destroyed here
它的行为就像一个堆栈。首先,构造基类,然后构造派生类。然后,它首先销毁派生类,最后销毁基类
<>这个行为对于大多数C++习语来说是非常重要的。
考虑这一点:
struct A {
A() : arr(new int[3]{1, 2, 3}) {}
~A() { delete[] arr; }
int* arr = nullptr;
};
struct B : A {
B() {}
~B() {}
auto stuff() -> int {
return std::accumulate(arr, arr + 3, 0);
}
};
auto main() -> int {
B b;
return b.stuff(); // returns 1 + 2 + 3
}
如果没有首先执行构造函数A()
,会发生什么情况?数组将为null。这将很糟糕
还有…如果析构函数~A()
没有执行会发生什么?那将是内存泄漏。那将非常糟糕
构造函数和析构函数有保证的执行和定义良好的顺序。这就是为什么不必调用super()
和~super()
在所有构造函数和析构函数中。因为您可能会忘记调用它。析构函数和构造函数不是您想忘记调用的东西,否则只使用C中的自由函数没有任何好处。在退出main期间删除对象。。但您确实删除了餐厅
此处-->返回0;
。当函数在其作用域中存在时,所有局部变量都会被销毁。您似乎误解了对象生命周期的工作方式……当“restaurant”对象超出作用域时,它仍然会被删除,这就是第二个“~B”的位置来自。我明白了,所以没有机会不在控制台中显示它?事实上,当它正在删除时,它是可以的,但我不想在控制台中显示它…并且您的基类中缺少一个虚拟析构函数。当您尝试一个base*b=new restaurant,
时,它会泄漏,即使您调用delete b;
对象是d退出main时删除。但您确实删除了restaurant
此处-->返回0;
。当函数在其作用域中存在时,所有局部变量都会被销毁。您似乎误解了对象生命周期的工作方式……当“restaurant”对象超出作用域时,它仍会被删除,这就是您的第二个“~B”的位置来自。我明白了,所以没有机会不在控制台中显示它?事实上,当它正在删除时,它是可以的,但我不想在控制台中显示它…并且您的基类中缺少一个虚拟析构函数。当您尝试base*b=新餐厅时,它会泄漏,
即使您调用delete b;
最好在此上下文中使用“自动存储”而不是“堆栈”之类的词。@SergeyA提到这两个词当然没什么坏处,谢谢。好的,我照你说的做了,它正在工作,谢谢你。@VidelIchinose如果你不删除,你就有内存泄漏。试着不要这样做。我对这个答案投了反对票。它建议泄漏一个对象,这