【发布时间】:2014-03-12 19:50:24
【问题描述】:
tl;博士
我想做这样的事情:
foo()
{
Y* p;
try {
p = new Y();
} catch {
//fix any problem that may have occured
}
// Now I know the object was fixed during catch or simply was created successfully.
p.do_something();
// win
}
我正在创建的对象正在使用一种有时不可靠的永恒资源。在没有必要预防措施的情况下尝试分配是很危险的。如果它确实失败了,有些事情是可以做的。但是,与我稍后展示的 switch 语句不同,似乎抛出异常不允许我解决 AFAIK 问题。
有人建议我从构造函数中抛出异常。但是,我不明白这如何证明是有用的,因为我看不到该异常将如何处理?我进行了搜索并找到了this example,但我不确定它是否真的是一种有用的可扩展方式来处理构造失败。
示例代码:
void f()
{
X x; //← if X::X() throws, the memory for x itself will not leak
Y* p = new Y(); //← if Y::Y() throws, the memory for *p itself will not leak
}
假设在p 之前分配的堆上的实例更多。他们不会因此而泄漏到内存中吗?所以函数f只是用来构造Y的一个实例。将“危险”构造移到另一种方法之外不是总是更有用吗?
我通常会做什么:
X* x = new X(); //No dangerous operation
switch (x.init()) // init returns int
{
case ...
// Handle failed init() here
}
这样做有缺点吗?好像比较靠谱。
【问题讨论】:
-
不要使用
new。然后问题就消失了。 -
或者,如果您必须使用
new,请使用unique_ptr或shared_ptr,这样当您离开作用域时,内存就会被释放。 -
更好的是对所有资源进行 raii-wrap,而不仅仅是内存。
-
也许你的构造函数有问题。如果你通过抛出异常来解决这个问题,那么你有两个问题。
-
问题与new无关。即使你在堆栈上构造一个对象或将一个对象插入到容器中,构造函数仍然会执行。
标签: c++ exception constructor