我阅读了“编程:使用 C++ 的原理和实践”一书 ( Bjarne Stroustrup )。有时作者写道:
catch (runtime_error e)
但有时他会写道:
catch (runtime_error& e)
据我所知,第一个变体创建源的副本,但第二个使用链接。还是我弄错了?在这种情况下,这对于“捕获”不重要吗?
我阅读了“编程:使用 C++ 的原理和实践”一书 ( Bjarne Stroustrup )。有时作者写道:
catch (runtime_error e)
但有时他会写道:
catch (runtime_error& e)
据我所知,第一个变体创建源的副本,但第二个使用链接。还是我弄错了?在这种情况下,这对于“捕获”不重要吗?
我原以为大多数时候,他会使用:
catch ( runtime_error const& e )
按值捕获和按引用捕获的区别与函数参数的按值传递和按引用传递完全相同。最重要的区别是,在按引用捕获时,动态类型可以是派生类型,按值会导致切片(因为复制)。
此外,如果您通过非常量引用捕获并修改异常对象,然后重新抛出,它将传播的是修改后的对象。
为了避免不必要的复制和切片,您应该始终通过引用捕获异常。尤其是在您打算重新安装的情况下throw;
。
按价值捕获
catch (runtime_error e)
与通过引用捕获
catch (runtime_error& e)
当您具有(通常是多态的)异常类层次结构并且希望在单个 catch 子句中捕获所有派生类型的异常时,您将使用后者。
例如,标准库中的所有异常类都派生自std::exception
,因此您可以执行以下操作:
try {
int i;
std::cin >> i;
switch (i) {
case 1: throw std::range_error();
case 2: throw std::overflow_error();
case 3: throw std::undefflow_error();
default: throw std::logic_error();
}
} catch (std::exception& e) {
// handle all the exceptions the same way,
// but print a diagnostic message polimorphicaly
std::cout << "I caught: " << e.what() << '\n';
}
如果不是通过引用,而是按值捕获,那么您总是会捕获一个std::exception
, 从对象的派生部分切下。
你应该总是通过引用来捕捉;绝对没有理由按价值追赶。
不要相信所写的一切。;-)