我真的不敢相信我找不到明确的答案......
在使用new
运算符初始化C++类构造函数抛出异常后,如何释放分配的内存.例如:
class Blah
{
public:
Blah()
{
throw "oops";
}
};
void main()
{
Blah* b = NULL;
try
{
b = new Blah();
}
catch (...)
{
// What now?
}
}
Run Code Online (Sandbox Code Playgroud)
当我尝试这个时,b
在catch块中是NULL(这是有道理的).
在调试时,我注意到conrol在它到达构造函数之前进入了内存分配例程.
这在MSDN网站上似乎证实了这一点:
当new用于为C++类对象分配内存时,在分配内存后调用对象的构造函数.
因此,请记住,b
永远不会分配局部变量(即在catch块中为NULL),如何删除分配的内存?
得到一个跨平台的答案也很好.即,C++规范说什么?
澄清:我不是在讨论类在c'tor中分配内存然后抛出的情况.我很欣赏在这种情况下,不会召唤人.我在谈论用于分配THE对象的内存(Blah
在我的例子中).
在C++中从错误条件退出构造函数的最佳技术是什么?特别是,打开文件时出错.
谢谢你的回复.我正在抛出异常.这是代码(不知道它是否是最好的方法,但它很简单)
// Test to see if file is now open; die otherwise
if ( !file.is_open() ) {
cerr << "Failed to open file: " << m_filename << endl;
throw ("Failed to open file");
}
Run Code Online (Sandbox Code Playgroud)
有人认为我喜欢C++,你不必在方法声明上声明抛出的异常.
我知道从析构函数中抛出异常是不安全的,但是从构造函数中抛出异常是不安全的?
例如,全局声明的对象会发生什么?使用gcc进行快速测试,我得到了中止,是否始终保证?你会用什么解决方案来迎合这种情况?
是否有任何情况下构造函数可以抛出异常而不是留下我们期望的东西.
编辑:我想我应该补充一点,我试图理解在什么情况下我可以获得资源泄漏.看起来明智的做法是手动释放我们在抛出异常之前通过构造获得的资源.我从来不需要在今天之前在构造函数中抛出异常,所以试图理解是否存在任何陷阱.
即这也安全吗?
class P{
public:
P() {
// do stuff...
if (error)
throw exception
}
}
dostuff(P *p){
// do something with P
}
...
try {
dostuff(new P())
} catch(exception) {
}
Run Code Online (Sandbox Code Playgroud)
分配给对象P的内存是否会被释放?
EDIT2:忘了提到在这种特殊情况下,dostuff将对P的引用存储在输出队列中.P实际上是一条消息,dostuff接收消息,将其路由到适当的输出队列并发送它.基本上,一旦dostuff持有它,它会在后来的dostuff内部释放.我想我想把一个autoptr放在P周围并在dostuff后调用autoptr上的释放以防止内存泄漏,这是正确的吗?
假设有这样的代码:
class CFoo
{
public:
CFoo()
{
iBar = new CBar();
}
private:
CBar* iBar;
};
....
CFoo* foo = new CFoo();
Run Code Online (Sandbox Code Playgroud)
执行上面的行时,将分配第一个内存来保存CFoo对象.但是如果新的CBar()行引发异常(由于内存不足),系统会自动解除分配先前分配给CFoo对象的内存吗?我认为它必须,但找不到任何明确的参考说明.如果没有,编码器将如何释放内存,因为它不会被分配给foo?
可能重复:
如何在C++中处理构造函数中的失败?
C++中是否有任何模式,所以如果出现故障,我可以在构造函数中终止对象创建?那么调用构造函数的客户端获得了有关失败的obj创建的信息?
简而言之,我的问题是将成员变量作为非托管C++中的指针.
在java或c#中,我们有"高级指针".实际上,我们无法意识到它们中的"指针".我们通常初始化类的成员,如下所示:
member = new Member();
Run Code Online (Sandbox Code Playgroud)
要么
member = null;
Run Code Online (Sandbox Code Playgroud)
但在c ++中,它变得更加混乱.我见过很多样式:使用new
,或者将成员变量保留在堆栈中.
在我看来,使用boost::shared_ptr
似乎很友好,但在boost本身的源代码中new
到处都有.这是效率的问题,不是吗?
是否有像"尽力避免new
"或其他什么的行会?
编辑
我意识到说"把它们留在堆栈中"是不恰当的,这里有一个更恰当的说法:当我需要一个object
成为我的成员变量时,我应该更喜欢一个而object
不是一个object*
?