06 August 2023

C++ 核心指南目录

“Throw by value, catch exceptions from a hierarchy by reference”

理由

以值的方式抛出异常(非指针),然后通过引用捕获,会阻止复制过程,导致产生对象的切片副本。

错误例子

void f()
{
    try {
        // ...
        throw new widget{}; // don't: throw by value not by raw pointer
        // ...
    }
    catch (base_class e) {  // don't: might slice
        // ...
    }
}

应该使用引用:

catch (base_class& e) { /* ... */ }

或者,最好用常量引用:

catch (const base_class& e) { /* ... */ }

大部分异常处理不会修改异常的值,所以,一般来说,我们建议使用 const

注意

对于小数值类型,可以以值的方式捕获,比如枚举类型。

注意

重新抛出捕获的异常,请使用 throw ,不要用 throw e; 。用 throw e; 会抛出 e 的一个副本。因为是复制操作,可能会由于类型不同,把原来的异常对象切片处理成 std::exception 。另外,还要注意,不要尝试在所有函数中,捕获所有异常,避免显式的 try/catch 操作。

强化

  • 当一个类型有虚函数,然后以值的方式被异常捕获,标记之。
  • 抛出原始指针的异常,标记之。