在C ++中执行默认的catch throw语句传递值或引用

时间:2012-03-05 05:32:13

标签: c++ exception

默认的catch语句catch(...) {}如何通过值或引用来捕获异常?

其次,默认抛出throw;如何通过值或引用抛出异常?

3 个答案:

答案 0 :(得分:8)

catch-all catch (...)根本不能让你访问异常对象,所以这个问题没有实际意义。 [更正:] 使用throw;重新抛出原始对象。如果处理程序按值捕获,则对本地副本的更改不会影响原始的,重新抛出的对象。 [/] 有关详细信息,请参阅15.3(特别是第17节)。

查看右侧的一些相关问题,例如this onethis one以及this onethis one

答案 1 :(得分:2)

你总能抓住你所抛出的东西。 假设你有一个异常类

class MyException {
public:
    int m_data;
    MyException(int data) 
    { 
        printf("MyException::MyException() ctor\n"); 
        m_data = data;   
    }

    MyException(const MyException & other)    { 
        printf("MyException::MyException() copy ctor\n");
    }

    ~MyException()
    {
        printf("MyException::~MyException() dtor\n");
    }
};

1)如果你抛出一个指针,你将得到指针:

示例1:

void f()
{
    throw new MyException()
}

void main()
{
    try{
        f();
    }    
    catch(MyException * ex) // You WILL catch the pointer
    {
        delete ex; // You should delete the exception object
    }
    catch(MyException & ex) // You WILL NOT catch the pointer
    {
    }
}

示例2:

void main()
{
     try{
         f();
     }
     catch(...) // You WILL catch the pointer, but will be unable to access it
     {
         throw; // You are rethrowing the pointer
     } 
 }

2)如果你抛出了一个对象,你会得到一个对它的引用:

示例1:

void f()
{
    printf("f BEGIN\n");
    throw MyException(1); // MyException ctor is called
    printf("f END\n");
}

void main()
{
    printf("main BEGIN\n");

    try
    {
        f();
    }
    catch(MyException & ex)  // You WILL catch a reference to created object
    {
       printf("catch MyException: %d\n", ex.m_data);
    } // MyException dtor is called here!!

    printf("main END\n");
}

生成以下输出:

main BEGIN
f BEGIN
MyException::MyException() ctor
catch MyException: 1
MyException::~MyException() dtor
main END

示例2:

void main()
{
     try
     {
         f();
     }
     catch(...)  // You WILL catch a reference to created object, 
                 //but will be unable to access it
     {
         throw; // You throw the reference
     }
 }

答案 2 :(得分:1)

抛出将抛出的值复制到实现定义的位置 因此,值会在throw上复制(这意味着类型必须是可复制的)。

当你抓住时,你可以选择按价值或参考来捕捉。

catch(X  val) // Catch by value
{
}
catch(Y& val) // Catch by reference
{
}

为什么要捕获的惯用语是通过const引用来捕获。这是因为如果按值捕获,则可以在将异常从其保存位置复制到catch值时进行切片。如果按值捕获,则会在catch块的末尾销毁该值。保存位置中的副本在try / catch块结束时被销毁(捕获并且不会被重新抛出)。

所以,当你遇到catch(...)时,没有任何事情发生。异常保留在未指定的位置,该异常已被复制到该异常中。

使用throw重新抛出异常时。 throw;。再没有任何事情发生,因为异常已经在未指定的位置,并且不需要发生任何事情。

注意:当没有异常传播时调用throw;是一个错误,将导致调用std :: terminate。