new一个对象之后怎么知道他是不是delete了

大鸟的小天空 2003-12-03 08:39:56
new一个对象
在多个函数中使用
怎么知道他最后是不是delete了
...全文
439 33 打赏 收藏 转发到动态 举报
写回复
用AI写文章
33 条回复
切换为时间正序
请发表友善的回复…
发表回复
ThinkX 2003-12-05
  • 打赏
  • 举报
回复
还记得在设计模式中有专门的创建型模式,其实对于C++或者ObjectPascal等没有GC的语言,也应该想想销毁型的模式。:)
在你的问题中,肯定要使数据和其显示分离更好些,也就是Observer或者Model/View。
明确所有权是好方法,但是chart的所有权当然不会是RadioButton了。
你可以创建一个类专门管理Chart的创建和销毁的。
下面有一段代码,很随意,我没有安装bcb所以没有经过调试。

enum ChartType { ctDot/*点状图*/, ctCylinder/*柱状图*/, .... };

class ChartManager
{
typedef std::list<TDBChart*> ChartList;
ChartList _charts;
public:
ChartManager() { }
~ChartManager() { Clear(); }

void Clear()
{
ChartList::iterator it = _charts.begin();
for (; it != _charts.end(); ++it)
{
if (*it != NULL)
delete *it;
}
_charts.clear();
}

TDBChart* CreateChart(TWinControl* owner, ChartType chartType)
{
TDBChart* chart;
switch (_chartType)
{
case ctDot:
chart = new TDBChart(owner);
//将_chart设置为点状图
break;
case ctCylinder:
chart = new TDBChart(owner);
//将_chart设置为柱状图
break;
...
}
_charts.push_back(chart);
return chart;
}

TDBChart* DestroyChart(TDBChart* chart)
{
ChartList::iterator it = std::find(_charts.begin(), _charts.end(), chart);
if (it != _charts.end())
_charts.erase(it);
delete chart;
}

TDBChart* ChangeChartType(TWinControl* owner, TDBChart* chart, ChartType chartType)
{
if (chart)
DestroyChart(chart);
return CreateChart(owner, chartType);
}
};


class TForm1 : public TForm
{
private:
ChartManager _chartManager;
TDBChart* _chart;
public:
__fastcall TForm1(TComponent*) : _chart(NULL) { }

void __fastcall RaidoButton1OnClick(TObject* sender)
{
ChartType ct;
switch (RaidoButton1.ItemIndex)
{
case 0:
ct = ctDot;
break;
case 2:
ct = ctCylinder:
break;
...
}

_chart = _chartManager.ChangeChartType(this, _chart, ct);
_chart.Parent = this;
}
};

大鸟的小天空 2003-12-05
  • 打赏
  • 举报
回复
大家也探讨了这么多了,总结一下方法。
1。明确所有权,进行有效的创建删除。
2。使用智能指针。
3。使用NULL指针。(很多人用,但是高手好像不用。哈哈)
那么就针对第一个方法,我再问一个问题。也算是为所有菜鸟问的。我自己还是不太明白所有权的问题。
我现在手头有个工作是这样的。
1。通过数据库查询,获得了6个数据源。
2。用tdbchart把这6个数据进行显示。
3。显示的时候可以是柱状图,点状图,曲线图。
那么我就要问了,在创建此tdbchart的Series的时候,这些Series的所有权是谁的。
我是通过RadioButton的选择来区分显示柱状图,点状图,曲线图的。那么在图形转换的时候(柱状-〉点状),事件发生在RadioButton的OnClick中的。那么就在此事件中创建和删除Serie对象。而次对像的所有权应该不是RadioButton的吧,那怎么来分析所有权。
我是这么分析的,哈哈,还请大虾指正。
还有个问题,我在RadioButton的OnClick中创建了Serie对像,这个对象是要显示的,不能再事件结束的时候删除掉吧。那么我这些Serie对象是不是应该声明为全局的,对于这些对象我该怎么管理。
谢谢大虾执教。
TopCat 2003-12-05
  • 打赏
  • 举报
回复
楼上,如果你的fm是局部变量,赋NULL是没什么意义的,如果要反复用到,delete之后赋NULL还是很不错的习惯。
iuIRCClient 2003-12-05
  • 打赏
  • 举报
回复
请问我在new一个Form的实例,showmodule使用后,就delete了,这个时候必须需要将指针再赋值为NULL吗?如:
TfmMain *fm=new TfmMain(this);
fm->ShowModule();
delete fm;
fm=NULL; //这一句是否必须要。

目前我写的一个程序运行一段时间后就出现了EOutOfResource错误,我估计是我在哪里的内存操作出了问题了。正在郁闷ing.
sczyq 2003-12-05
  • 打赏
  • 举报
回复
因为一个类或实例,所能引用的只是指针,也就是内存地址.

看看NULL吧, 他是指向0,表求没的实例.

如果你连 obj = NULL 都懒得写,那你就得让你的用户学会忍耐!
TopCat 2003-12-04
  • 打赏
  • 举报
回复
to jiangchun_cn:

NULL指针可以算是解决这个问题的最廉价的方法,我不觉得他有什么不好。

delete this本身也并不是一个好的习惯,为了能保证delete this不出错,本身也是要做很多工作的,你完全可以在做这些工作的时候多做一点来保证不会二次删除。

其实C++有smart-pointer的解决方案,可以用来解决这个问题。虽然现在还没有放之四海而皆准的方案,但是始终是可以找到一个来适合你的应用的。当然,这是在你能忍受该方案所带来的复杂度和额外性能降低的前提下的。
Bkoklam 2003-12-04
  • 打赏
  • 举报
回复
呵呵! hy1080(老神经病) 朋友很有幽默感啊!
赞同 plainsong(短歌),他解释的已经是很专业了,TObject *Obj=new TObject(this)来创建对象,用完后用delete来删除它,否则程序不会自动删除对象;直到退出程序为止。
heng2003 2003-12-04
  • 打赏
  • 举报
回复
我一般这么做
char * s = NULL;
try{
s = new char[111];

}catch(...){

}
//用完
if(s) {delete [] s; s = NULL; }
不管try 块里面正确执行完毕或是出异常了,最后都能删除s(或是根本s 没有申请到空间)
penu 2003-12-04
  • 打赏
  • 举报
回复
可以设一个全局变量bool exist;
在new 一个对象前检查:
if (!exist)
xxx = new Txxx();
在对象的类构造函数中添加如下代码:
exist = true;
在对象的类析构函数中添加如下代码:
exist = false;
在判断对象是否delete时只需要判断exist的值即可:
exist == true : 对象存在
exist == false : 对象已被delete

不过这种方法不太规范。

总之只能说:小心些,再小心些!
jiangchun_xn 2003-12-04
  • 打赏
  • 举报
回复
为什么这么多人喜欢用NULL指针来做这种判断。

1。有delete this的对象怎么办???
2。Owner删除所带来的对象删除怎么办???
3。你能保证这个风格一直在你的程序中么???


个人建议:

如果需要掌握一个对象的是否delete,应该建立类似Object的某种装载类的东西(这个类可以用Singleton模式)来,比如在Screen里面插找某个Form指针等等。

sczyq 2003-12-04
  • 打赏
  • 举报
回复
// 声明时:
TMyObject* obj=NULL;

// 必须建立时
if (!obj)
{
obj=new TMyObject();
}

//操作时
if (obj)
{
obj->...... // 对obj 操作
}


//删除时
if (obj)
{
delete obj;
obj=NULL;
}
踏岸寻柳 2003-12-04
  • 打赏
  • 举报
回复
一般情况下我会用一下两种方法:
1. 即用即删
T×× *pT××;
try
{
*pT×× = new T××();
// 对象操作...
}
__finally
{
delete pT×;;
}

2. 声明为全局变量,这样随时都可以申请空间,在最后FormDestory时判断一下对象、销毁对象。


另外,plainsong(短歌)提供了一个很不错的想法,可以随时随地声明对象、创建对象,在最后应用程序退出时对set进行操作即可。
另,也可以使用list。
书生 2003-12-04
  • 打赏
  • 举报
回复
。。。
ljianq 2003-12-04
  • 打赏
  • 举报
回复
TMyObject* obj=NULL;

if (!obj) {
obj=new TMyObject();
}

//操作

//删除时
delete obj; //obj=NULL时,也不会错。

obj=NULL; //不要忘记
ThinkX 2003-12-04
  • 打赏
  • 举报
回复
同意plainsong(短歌)和 TopCat(令狐虫)。
使用RAII进行函数区域内的清除工作是十分简洁的,在C++代码中还是尽量避免使用__finally,除非正在使用VCL。

template <typename T>
class ScopeGuard
{
T* _p;
ScopeGuard(const ScopeGuard&);
ScopeGuard& operator=(const ScopeGuard&);
public:
explicit ScopeGuard(T* p) : _p(p) { }
~ScopeGuard() { if (_p) delete _p; }
};

SomeClass* obj = new SomeClass();
ScopeGuard<SomeClass> guard(obj);

如果是全局变量的清除,可以将ScopeGuard作为static的全局变量对资源进行保护。
如果要是更加复杂的全局共享,那么就应该单独提取出管理对象生存这一部分作为一个单独的模块了。
短歌如风 2003-12-04
  • 打赏
  • 举报
回复
new TButton(this)的方法是可以自动释放的,它会在"this"释放时释放;但手动释放也是安全的,因为TComponent的析构函数会把自己从Owner(如果有的话)的子控件列表中去除。

如果使用NULL方案解决,如果你是在操作VCL对象,可以用FreeAndNil来释放,释放后自动置为NULL;如果是其它对象,也可以自己写一个:
template <typename T>
void FreeAndNil(T*& Obj)
{
T* temp = Obj;
Obj = NULL;
delete temp;
}

不过我认为还是应该明确所有权。多个函数/对象会访问同一个对象时,应该只有一个函数/对象会释放这个对象,并且保证释放后这个对象不会再被使用中,而其它使用者不需要去判断。

至于后来楼主贴的代码是在同一个函数中,在产生异常时无法判断的问题,这时还是不需要判断,完全可以用RAII技术解决——比如用auto_ptr。我不赞同使用__finally来处理异常,既然用的是C++,完全可以不用象Object Pascal那样使用难看的try-finally结构。

auto_ptr不能处理动态分配的对象数组——它会调用delete而不是delete[],但我不认为用new[]分配对象数组是个好主意,应该用vector。

此外,delete Button在Button是一个合法的,用new分配的TButton(假设)对象时是不会抛出异常的。它只调用了TButton的析构函数和内存释放函数,析构函数抛出异常会导致程序终止,而内存释放不会抛出异常。

最后说一句,在处理可能发生异常时的释放问题时,在Object Pascal中由于没有RAII技术可用,我正是使用NULL方法来处理释放问题的。
TopCat 2003-12-04
  • 打赏
  • 举报
回复
to jiangchun_xn :

那样就变成一个责任心的问题了,不在此帖讨论范围之内,呵呵。而且针对这个问题写一个简单的wrapper甚至是宏都不难。

我只是说NULL方法没必要批判,毕竟在大多数情况下还是很好用的。
kyodan 2003-12-04
  • 打赏
  • 举报
回复
楼主的问题应该是对象管理方面的,但是从下面提供的问题代码来看,用__finally就能解决了啊
jiangchun_xn 2003-12-04
  • 打赏
  • 举报
回复
TopCat(令狐虫):

Hehe!你看,这里有很多人没有这个习惯的,难道他们一定错了么?假如又一个是你的同事,你们在一起你能保证大家不会出冲突么?~_^
jiangchun_xn 2003-12-04
  • 打赏
  • 举报
回复
从楼主的意思看,似乎是一个生命期长的单个实例,为什么不用单实例模式呢?
加载更多回复(13)

13,825

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder相关内容讨论区
社区管理员
  • 基础类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧