关于new操作符的问题。

jianliang79 2004-04-19 07:48:50
假如用new操作符创建一个对象时,这个对象的构造函数抛出一个异常,而创建这个对象的代码catch了这个异常,那么请问在C++抛出异常进行UnWind处理过程中会不会将new操作符之前用malloc分配的那块内存释放。其程序示例如下:

class CExp {
CExp() {}
~CExp() {}
};

class CTest {
CTest() { throw CExp(); }
~CTest() {}
}

int main()
{
CTest * pTest = NULL;

try {
pTest = new CTest;
} catch ( CExp * pe ) {
// 此时pTest为NULL,那么new操作符为CTest分配的内存
// 是否已经正常释放;如果没有的话,我现在又该怎样
// 释放它呢?请高手指教。
}
}
...全文
57 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
holyfair 2004-04-20
  • 打赏
  • 举报
回复
构造函数代码的执行之前将分配给一个构造对象的空间出来,然后去执行
构造函数内代码.所以空间是不会自动释放掉的.
不建议这种风格,所以实在要做,一定要有个判断机制,失败则调用delete
释放内存.
wbh0360 2004-04-20
  • 打赏
  • 举报
回复
有收获
zhouqingyuan 2004-04-20
  • 打赏
  • 举报
回复
构造函数抛出异常,后果是分配的内存无人引用的,成了野的了。
zhouqingyuan 2004-04-20
  • 打赏
  • 举报
回复
除了你自己,没有谁负责帮助释放内存的,所以一般最好能让类构造函数尽量简单保证运行成功的。那块内存无对象引用,所以除非有Garbage Collection这种东西,否则那块内存一直悬那里。
yym314 2004-04-20
  • 打赏
  • 举报
回复
不会释放的!
另外我记的那本书上说不要在构造函数抛出异常,如果一定要判断构造是否成功的话可以这样做:

class CTest
{
....
CTest( int& retVal )
{
try
{
//doing some thing
}
catch ( CExp * pe )
{
// constructor failed, set retVal;
retVal = -1;
}
}



int main()
{
int iRetVal = 0;
CTest * pTest = new CTest( iRetVal );
if( iRetVal == -1 ) //constructor failed
{
delete pTest;
return -1;
}
.............
return 1;
}
ToIP 2004-04-20
  • 打赏
  • 举报
回复
不会释放的,除非进程结束,或者程序中显式delete

另外用new产生对象时需要判断是否成功,if(pTest == NULL)//...

delete pTest;
//此时pTesth并不等于NULL
//需要把它复位
pTest = NULL;
jianliang79 2004-04-20
  • 打赏
  • 举报
回复
happlyman 2004-04-20
  • 打赏
  • 举报
回复
这样的话就是在构造函数对数据成员做初始化的时候发生的异常也能catch到

不好意思,上面的我写错了应该如下:
class CTest
{
....
CTest( int& retVal )
try{
//doing some thing
}
catch ( ... )
{
// constructor failed, set retVal;
retVal = -1;
}
happlyman 2004-04-20
  • 打赏
  • 举报
回复
构造函数中可以抛出异常,但是最好也在构造函数中去catch,  yym314(小鸟)   的方法还是会有问题:应该这样:

class CTest
{
....
CTest( int& retVal )
try{
//doing some thing
}
catch ( CExp * pe )
{
// constructor failed, set retVal;
retVal = -1;
}

也就是把try块和函数体放在一块儿
jianliang79 2004-04-20
  • 打赏
  • 举报
回复
前面诸位大侠都提供了宝贵意见,我在这里总结一下:
1)通过new操作符创建对象,如果对象的构造函数中抛出异常(这个异常不在构造函数中catch)的话,那么就会产生内存泄漏。
2) yym314(小鸟) 大侠提出了在构造函数catch异常,这个异常并不向外throw,而是通过一个构造函数的参数来通知其创建者的办法。顺便向 oyd(cplusplus) (MVP) 大侠说一句,这种方法确实是有人使用的,在DirestShow的基类库这种方法使用很普遍。
3) zhouqingyuan(浪帆) 大侠建议构造函数尽量简单,不要将可能出现失败的工作加进去。
另外 cgsw12345(cgsw) 大侠还提出了auto_ptr类,但这个类我不熟悉,还请cgsw12345(cgsw) 大侠介绍介绍。

目前来讲,我是肯定不会在构造函数向外抛出异常了,因为这样会导致内存泄漏。第二种和第三种方法看来是比较可行的,还请大家帮我分析分析,到底用哪一种方案?谢谢。
goodname 2004-04-20
  • 打赏
  • 举报
回复
回复人: Wolf0403(完美废人)(期待有一天。。。)


class RscCluster
{
...................................
private:
int * p1, p2, p3;
};


这里p2,p3不是指针吧?


oyd 2004-04-20
  • 打赏
  • 举报
回复
为什么不在构造函数抛异常?
构造出异常,充其量也就是构造不成功,但是它不会给你一个非法的对象。
事实上,标准的报错方式就是在构造函数中抛出一个异常。
而象下面这样做
class CTest
{
....
CTest( int& retVal )
{
try
{
//doing some thing
}
catch ( CExp * pe )
{
// constructor failed, set retVal;
retVal = -1;
}
}



int main()
{
int iRetVal = 0;
CTest * pTest = new CTest( iRetVal );
if( iRetVal == -1 ) //constructor failed
{
delete pTest;
return -1;
}
.............
return 1;
}
是极为龌龊的,你们有谁见过哪个库的构造函数是这么使用的??

MFC那个CBrush例子,你这样用就可以了
CBrush brush;
Wolf0403 2004-04-20
  • 打赏
  • 举报
回复
class RscCluster
{
public:
RscCluster()
:p1(0), p2(0), p3(0)
{
auto_ptr<int> ap1(new int());
auto_ptr<int> ap2(new int());
auto_ptr<int> ap3(new int());
p1 = ap1.release();
p2 = ap2.release();
p3 = ap3.release(); // 因为 auto_ptr 操作都是 throw(),所以顺序无关紧要。
}
private:
int * p1, p2, p3;
};
cgsw12345 2004-04-20
  • 打赏
  • 举报
回复
不会自己释放,要程序员自己进行处理。
看MEC中的这样做的:
BookEntry::BookEntry(const string& name,
const string& address,
const string& imageFileName,
const string& audioClipFileName)
: theName(name), theAddress(address),
theImage(0), theAudioClip(0)
{
try { // 这try block是新加入的
if (imageFileName != "") {
theImage = new Image(imageFileName);
}
if (audioClipFileName != "") {
theAudioClip = new AudioClip(audioClipFileName);
}
}
catch (...) { // 捕获所有异常
delete theImage; // 完成必要的清除代码
delete theAudioClip;
throw; // 继续传递异常
}
}
在对象构造中,处理各种抛出异常的可能,是一个棘手的问题,但是auto_ptr(或者类似于auto_ptr的类)能化繁为简。它不仅把令人不好理解的代码隐藏起来,而且使得程序在面对异常的情况下也能保持正常运行。
sharkhuang 2004-04-20
  • 打赏
  • 举报
回复
不会自己释放的.
jianliang79 2004-04-20
  • 打赏
  • 举报
回复
前面几位说得非常明白了。
但假如我要创建一个CBrush类的对象,而且构造函数利用CBrush::CBrush(int nIndex, COLORREF crColor)这种形式,而这个构造函数的实现如下:
CBrush::CBrush(int nIndex, COLORREF crColor)
{
if (!Attach(::CreateHatchBrush(nIndex, crColor)))
AfxThrowResourceException();
}
那么万一我在new CBrush(i, color)的时候由于无法分配brush资源而抛出异常的话,那我就没有办法释放CBrush类对象的内存了。这难道是MFC设计上的失误吗?

64,637

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

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