避免异常处理中的副本

时间:2011-05-26 19:48:23

标签: c++ exception-handling

我可以通过以下方式避免复制对象吗?

MyClass Obj;

try {
    throw &Obj;
}
catch(MyClass *a) {

}

4 个答案:

答案 0 :(得分:10)

如果对象太昂贵而无法复制,则不应将其作为异常抛出 - 完全停止。异常类应该相当简单和轻量级。并且你应该总是通过引用捕获异常(可能通过const引用) - 捕获指针是糟糕的风格。所以你的代码应该写得更好:

try {
    throw MyClass();
}
catch( const MyClass & a) {
}

在回复您的评论时,请:

struct A {
    A() {}
    private:
    A( const A & ) {}
};

int main() {
    throw A();
}

应该是一个错误。但是你根本不应该禁止复制你想要抛出的类作为例外 - 你为什么要这样做?

答案 1 :(得分:2)

不要这样做。

考虑这个程序:

#include <iostream>
#define X() (std::cout << __FUNCTION__ << "\n")

struct MyClass {
 MyClass() { X(); }
 ~MyClass() { X(); }
};

void f() {
 MyClass Obj;
 throw &Obj;
}

int main() {
 try {
  f();
 } catch(MyClass *a) {
  X();
 }
}

其输出为:

MyClass
~MyClass
main

请注意,在程序进入catch块之前,销毁了指向对象。这意味着我们不能在catch块中取消引用a,严重限制其有用性。

答案 2 :(得分:0)

避免复制异常对象的唯一方法是将指针抛出到对象中,就像在示例中所做的那样。您必须确保对象是静态的或堆分配的,而不是在抛出期间离开代码块后将消失的本地对象。

修改:我想到了另一种方法。您可以使用指针作为成员创建自己的异常类(应该从std::exception或其子节点派生),然后抛出它。如果您使用智能指针(如shared_ptr),则无需担心所包含对象的生命周期。

答案 3 :(得分:0)

语法正确并且避免了复制,因为传递了引用。但是,通常会构造一个标准的无名异常对象,并由catch语句捕获。