我刚开始使用RAII在C ++中,并设置了一个小的测试案例。 无论是我的代码是深感困惑,或RAII不工作! (我猜是前者)。
如果我运行:
#include <exception>
#include <iostream>
class A {
public:
A(int i) { i_ = i; std::cout << "A " << i_ << " constructed" << std::endl; }
~A() { std::cout << "A " << i_ << " destructed" << std::endl; }
private:
int i_;
};
int main(void) {
A a1(1);
A a2(2);
throw std::exception();
return 0;
}
与异常注释掉我得到:
A 1 constructed
A 2 constructed
A 2 destructed
A 1 destructed
如预期,但与例外,我得到:
A 1 constructed
A 2 constructed
terminate called after throwing an instance of 'std::exception'
what(): std::exception
Aborted
所以我的对象不是破坏,即使它们走出去的范围。 这难道不是对RAII整体基础。
指针和更正非常感谢!
Answer 1:
你不必为你的异常处理程序。 当发生这种情况的标准说的std ::终止被称为,这反过来调用中止。 见14.7中的C ++编程语言,第三版。
Answer 2:
问题是, main
具有特殊的地位。 当异常是从那里扔,堆栈无法解开有意义,应用程序只是调用std:terminate
代替。
然后它使一个有点感觉,为什么变量不走的范围了。 我们还没有真正留在他们所宣称的范围 。 出现什么情况可以被认为是等价于:
int main(void) {
A a1(1);
A a2(2);
std::terminate();
}
(我相信这是实现定义的析构函数是否被称为在这种情况下,虽然如此,在某些平台上,它会如你预期工作)
Answer 3:
你必须在主,这意味着调用终止unhanded例外。 试试这个:
int main(void)
{
try
{
A a1(1);
A a2(2);
throw std::exception();
return 0;
}
catch(const std::exception & e)
{
return 1;
}
}
Answer 4:
如果一个异常逸出主()是实现定义天气堆栈退绕。
尝试
int main()
{
try
{
doWork(); // Do you experiment here.
}
catch(...)
{ /*
* By catching here you force the stack to unwind correctly.
*/
throw; // re-throw so exceptions pass to the OS for debugging.
}
}
Answer 5:
正如其他人所指出的那样,你有一个未捕获的异常,(),它调用终止。 它是实现定义(见的标准,15.3条第9款和15.5.1条第2款)的析构函数是否被称为在这种情况下,在您的实现的定义显然是“不,他们不会。” (如果终止()被调用任何其他原因不是抛出不具有处理程序的例外,析构函数不会被调用。)
Answer 6:
你一个对象没有被破坏,因为的std ::终止被调用。
的std ::终止时调用的未处理的异常漏出为主。 如果你在一个try / catch(即使赶上刚刚重新加注)包装你的代码,你会看到您所期望的行为。
Answer 7:
您没有正确处理异常,所以对象超出范围之前,您的应用程序退出。
我要解释一下。 如果一个异常“气泡”到主堆栈退绕(编辑)。 即使代码移动到一个辅助功能将不解决这个问题。 例如:
1 #include <exception>
2 #include <iostream>
3
4 void test();
5
6 class A {
7 public:
8 A(int i) { i_ = i; std::cout << "A " << i_ << " constructed" << std::endl; }
9 ~A() { std::cout << "A " << i_ << " destructed" << std::endl; }
10 private: int i_;
11 };
12
13
14 int main(void) {
15 test();
16 return 0;
17 }
18
19 void test(){
20 A a1(1);
21 A a2(2);
22 throw std::exception();
23 }
上面的代码将不会解决问题。 解决这个问题的唯一办法是包装抛出的异常在try-catch块。 这将保持异常到达主,并停止终止对象超出范围之前,正在发生。
Answer 8:
还有人建议把一个try / catch里面main()
来处理这个问题,工作正常。 出于某种原因,我发现很少使用“功能,尽量块”更好看,这令我感到奇怪(我认为它看起来太奇怪了)。 但我不认为有任何真正的优势:
int main(void)
try
{
A a1(1);
A a2(2);
throw std::exception();
return 0;
}
catch (...)
{
throw;
}
一对夫妇的缺点是,因为它很少使用,不少开发商抛出了一个循环,当他们看到它,VC6它扼流圈,如果这是一个考虑因素。
Answer 9:
由于异常没有被达到的main()时被处理,它会导致调用标准::终止(),实际上需要相当于
int main(void) {
A a1(1);
A a2(2);
exit(1);
}
析构函数不能保证在他们走出去的范围之前,程序终止的情况下被调用。 对于RAII另一个孔,可以考虑:
int main(void) {
A *a1 = new A(1);
}
Answer 10:
下面的代码工作。
#include <exception>
#include <iostream>
class A {
public:
A(int i) { i_ = i; std::cout << "A " << i_ << " constructed" << std::endl; }
~A() { std::cout << "A " << i_ << " destructed" << std::endl; }
private:
int i_;
};
void test() {
A a1(1);
A a2(2);
throw std::exception();
}
int main(void) {
try {
test();
} catch(...) {
}
return 0;
}
文章来源: C++ RAII not working?