Whe*_*050 4 c++ pointers destructor
我遇到了对C++指针缺乏深刻理解的问题.我写了一个名为Skymap的类,它有以下定义:
class Skymap {
public:
Skymap();
~Skymap();
void DrawAitoffSkymap();
private:
TCanvas mCanvas;
TBox* mSkymapBorderBox;
};
Run Code Online (Sandbox Code Playgroud)
功能定义为:
#include "Skymap.h"
Skymap::Skymap()
{
mCanvas.SetCanvasSize(1200,800);
mMarkerType=1;
}
Skymap::~Skymap()
{
delete mSkymapBorderBox;
}
void Skymap::DrawAitoffSkymap()
{
TBox* mSkymapBorderBox=new TBox(-200,-100,200,100);
//Use the mSkymapBorderBox pointer for a while
}
Run Code Online (Sandbox Code Playgroud)
(我正在使用ROOT绘图包,但我认为这只是一个普通的C++问题).
现在,以下程序在到达skymap2的析构函数时会崩溃:
int main(){
Skymap skymap1;
Skymap skymap2;
skymap1.DrawAitoffSkymap();
skymap2.DrawAitoffSkymap();
return(0);
}
Run Code Online (Sandbox Code Playgroud)
但是,以下内容不会崩溃:
int main(){
Skymap skymap1;
skymap1.DrawAitoffSkymap();
return(0);
}
Run Code Online (Sandbox Code Playgroud)
此外,如果我在构造函数中将指针mSkymapBorderBox初始化为NULL,则在执行第一个程序(使用2个Skymap对象)后,我不会再遇到崩溃.
任何人都可以解释一下其根本原因是什么?它似乎是第二个Skymap对象中指针的问题,但我看不出它是什么.
Naw*_*waz 16
TBox* mSkymapBorderBox=new TBox(-200,-100,200,100);
Run Code Online (Sandbox Code Playgroud)
在这里,您将内存分配给局部变量,而不是成员变量.而且由于您没有为成员变量分配内存,因此调用delete它会调用未定义的行为,这会导致您的情况崩溃.
你应该做的是这样的:
mSkymapBorderBox=new TBox(-200,-100,200,100);
Run Code Online (Sandbox Code Playgroud)
现在为成员变量分配内存.这是为什么局部变量的名称与成员变量不同的原因之一.命名约定有助于避免此类错误.
作为旁注,或者说非常重要的注释,由于您的类管理资源,请考虑正确实现复制语义和析构函数:此规则通常被称为"三规则".或者使用一些智能指针,例如std::shared_ptr,std::unique_ptr或者你的场景中适合的任何东西.
纳瓦兹的回答是正确的.但除此之外,您的代码有几个可能的问题:
修理:
(1)在构造函数中将mSkymapBorderBox初始化为零.
(2)决定如果多次调用DrawAitoffSkymap应该做什么.如果它应该重用旧的mSkymapBorderBox,那么你会想要说:
void Skymap::DrawAitoffSkymap() {
if (!mSkymapBorderBox) mSkymapBorderBox = new TBox(...);
...
}
Run Code Online (Sandbox Code Playgroud)
另一方面,如果每次都要创建一个新的TBox,那么你想要:
void Skymap::DrawAitoffSkymap() {
delete mSkymapBorderBox; // note: does nothing if mSkymapBorderBox == 0
mSkymapBorderBox = new TBox(...);
...
}
Run Code Online (Sandbox Code Playgroud)