返回信息流看TIC++,卷2,那个猫和狗的例子。
class UseResources {
Cat *bp;
Dog *op;
public:
UseResources (int sz=3) {
*bp = new Cat[sz];
*op = new Dog;
}
};
他的意思是,当红色语句由于内存不足丢出异常以后,Dog的内存申请没有成功,Cat的那个数组申请成功,但是由于抛出异常,析构函数没有执行,无法释放,造成内存泄漏。
提供的解决方案是把那两个指针包裹在两个模板类中。调用的示意如下:
class UseResources {
PWrap<Cat, 3> C;
PWrap<Dog, 1> D;
public:
UseResources: C(), D() {};
};
要说区别,就是把对内存的申请,由构造函数内移入了初始化列表。
我的问题是,初始化列表这个过程是原子性的么?如果初始化列表失败了,就会释放Cat的那个数组么?没有想明白。
这是一条镜像帖。来源:北邮人论坛 / cpp / #9104同步于 2008/7/3
该镜像源已超过 30 天没有更新,可能在源站已被删除。
CPP机器人发帖
关于 初始化列表 失败
ericyosho
2008/7/3镜像同步4 回复
订阅后,新回复会通过你的通知中心匿名送达。
4 条回复
【 在 ericyosho 的大作中提到: 】
: 要说区别,就是把对内存的申请,由构造函数内移入了初始化列表。
: ...................
不对,区别在于把对内存的申请放入了另外一个对象里面,其实就是资源管理思想(RAII)的运用。在这个例子里面,你写不写初始化列表效果是一样的,它都照样会调用C和D的默认构造函数。关键是异常的问题,当抛出异常的时候,如果你在外面某一级把这个异常try catch住了,它会正常析构掉已经正确构造的局部对象,也就是在D被构造之前,C已经被正常构造了的话,抛出异常的时候C会被正常地析构。
至于异常实现的机制,我也并不是很清楚,就大概知道,如果你使用了try catch的话,编译器会自动插入一些处理的代码,实际上它使用的是操作系统提供的结构化异常(SEH)来完成的,Java/.net的异常实现也都是用SEH来完成的。然后抛出异常的时候,会沿着调用链反向进行栈开解(Stack Unwind),析构掉已经成功构造的局部对象,直至遇上合适的try catch
至于一些具体的异常细节问题尤其是SEH,那可要请教茫猪这些研究底层的大牛了~~
楼上说的这个,是集中在,如果有合适的 catch 子句被执行时。
那我们能不能这样想,如果在前面的那种裸指针的时候,如果用好 try catch ,并写好合理的处理语句,我们同样可以保证没有内存的泄漏呢?
还有,如果没有合适的 catch 子句被执行呢?又会有啥情况?
【 在 ericyosho 的大作中提到: 】
: 楼上说的这个,是集中在,如果有合适的 catch 子句被执行时。
: 那我们能不能这样想,如果在前面的那种裸指针的时候,如果用好 try catch ,并写好合理的处理语句,我们同样可以保证没有内存的泄漏呢?
: 还有,如果没有合适的 catch 子句被执行呢?又会有啥情况?
在baidu搜到这个
http://zyliusunny.bokee.com/viewdiary.13335374.html
在effective系列应该会讲有这些问题,你可以去翻翻