我正在尝试理解以下程序。执行时出现错误,如下所示。
#include<iostream>
using namespace std;
class Base
{
public:
int *a;
int a1;
int b;
Base(){
cout<<"Inside Constructor"<<endl;
a1 = 10;
a = &a1;
cout<<" "<<a<<endl;
b = 20;
}
Base(const Base &rhs)
{
cout<<"Inside Copy Constructor"<<endl;
a = new int;
*a = *(rhs.a);
b = rhs.b;
}
~Base(void)
{
cout<<"Inside destructor"<<endl;
delete a;
}
};
int main()
{
Base obj;
Base obj2(obj);
cout<<"obj a "<<*(obj.a)<<" b "<<obj.b<<endl;
cout<<"obj2 a "<<*(obj2.a)<<" b "<<obj2.b<<endl;
obj.a1 = 30;
obj.b = 40;
cout<<"obj a "<<*(obj.a)<<" b "<<obj.b<<endl;
cout<<"obj2 a "<<*(obj2.a)<<" b "<<obj2.b<<endl;
return 0;
}
执行此代码时,我得到以下输出
Inside Constructor
Inside Copy Constructor
obj a 10 b 20
obj2 a 10 b 20
obj a 30 b 40
obj2 a 10 b 20
Inside destructor
Inside destructor
Segmentation fault
[编辑]我正在寻找一种方法来破坏我在复制构造函数中创建的堆内存。那么这里能做什么呢?请建议
[编辑]
删除应该只使用new在堆分配的内存上使用。
a1 = 10;
a = &a1;
在您的情况下,"a"将内存地址保存在堆栈中。因此,您不应该在该内存上调用 delete。
您必须删除使用 new
(动态分配)获取的内存,而不是自动存储变量。
在复制构造函数中,您正在使用 new 运算符为指针 a 分配内存,以便您可以删除它。但由于您没有在默认构造函数中使用 new 运算符,因此您可以删除指针 a 。您必须使用删除操作器来释放堆中而不是堆栈中的变量的内存。
当您使用 new 运算符时,变量是在堆中创建的,其中作为局部变量是在堆栈内存中创建的,无法使用删除运算符删除
问题不在于复制构造函数,问题在于您没有始终如一地使用new
(如果您使用 move,那么也许您会有道理)。你有一些选择。我试图变得有用,而不是详尽无遗,也许我错过了其他好的设计理念。
始终(并始终)使用new
您可以在所有构造函数中放置一个新的,因此,析构函数将始终能够调用 delete
。即使你不需要它。这可能是一个丑陋的黑客,但始终如一。
切勿使用new
如果您从不使用new
,则也不使用delete
,编译器可确保一致性并确保您不会搞砸。通常,您可以依赖构造函数上的编译器默认行为。
使用智能指针
如果不是手动调用delete
而是将变量保存在unique_ptr
中,那么编译器将在析构函数中自动释放它。智能指针足够智能,可以知道它是否已初始化。
请注意,使用智能指针意味着您永远不应该调用delete
,因为如果您在没有警告智能指针的情况下这样做,您将偶然发现同样的问题。如果您不熟悉它们并且正在使用 C++11,那么学习:)是一件好事
跟踪指针的状态
我不会保证这一点。看起来很C
,不C++
.但是,您始终可以跟踪bool
值并在销毁时对其进行检查。这就像使用智能指针一样,但需要内部实现。我认为这是一个糟糕的设计理念,尽管在某些情况下具有教育意义。