C ++ RAII不工作?(C++ RAII not working?)

2019-07-29 22:57发布

我刚开始使用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?