在 catch 块异常中无意义地使用引用传递语法
Meaningless use of pass by reference syntax in catch block- exception?
我的示例代码:
#include<iostream>
using namespace std;
class Test{ public: int set;};
Test T;
int main()
{
T.set = 100;
try{
throw T;
}
catch(Test &T)
{
T.set = 0;
}
cout<<T.set<<endl;
return 1;
}
在这里,我通过引用捕获抛出的 T 对象并在 catch 块中修改其值。为什么T
对象在catch
块之后仍然打印100
?在这种情况下,引用语法按值传递有什么用?
编译器:GCC 5.1.0
您通过引用捕获异常对象,但不将其抛出。
异常总是"按值抛出">,因为它们必须分配给进程内存中不受堆栈展开影响的特殊区域。
[C++14: 15.1/3]:
抛出异常副本初始化 (8.5, 12.8( 一个临时对象,称为异常对象。临时值是一个左值,用于初始化在匹配处理程序 (15.3( 中声明的变量。[..]
这是一个一般规则,旨在解释更常见的情况,其中T
实际上是try
块本身或其封装函数的局部情况。如果不复制它,则不可能从调用范围中捕获它。
我们通过引用捕获异常对象,这样您就不会不必要地再次复制已复制的T
。它还会在异常位于继承层次结构中时防止切片。有时人们使用它来改变异常对象,然后再将其重新抛出到调用范围,尽管这似乎
通过引用 to- const
捕获它与通过引用 to const
捕获任何其他事物具有相同的好处:它确保您不会改变异常。如果你不重新抛出它,那么这里就没有实际的好处,但如果像我一样,你默认编写const
作为防止错误的故障保险,那么没有理由不使用它。
"> 为什么 T 对象在 catch 块之后仍然打印 100?
因为抛出是按值,所以创建一个副本。
"> 在这种情况下,引用语法按值传递有什么用?
无。
参考const
捕获是一个很好的经验法则,因为它通常是高效和安全的。
上面的代码,就像我写这篇文章时的代码一样,没有通过引用const
来捕获,所以这只是 (1(不好的做法。
顺便说一下,谈到良好做法,使用所有大写名称可能会与宏名称发生冲突,并且(在这种情况下是误导性地(向训练有素的读者指示宏。
单字母大写名称,尤其是T
,在某种程度上是一种特殊情况,因为它们按照惯例已用于模板参数,因此它们不太可能用作宏名称。
不过,我还是推荐旧的约定,宏全大写,总是,其他任何东西都是混合或小写的。
1(曾经,C++98和C++03标准的措辞可以解释为仅通过提及非const
保证的效率来捕获。这是一种特殊的解释,但至少有一个著名的C++人士提倡。它现在只是具有历史意义。
- 很好的语法来获取对向量/数组数据的大小引用?
- C++:取消引用十六进制值,有点语法问题
- 解释通过从函数引用返回数组的语法
- 将引用绑定到指针的语法是什么?(各种)
- 访问对象的取消引用值的语法
- 统一取消引用语法是否可行?
- 将此类传递给引用的正确语法是什么?
- 解压缩C++指针/引用语法
- 引用变量何时合适,为什么?你能解释一下实际的语法和位置吗?
- C++构造函数中的语法错误 - arugment 是对另一个类中的对象的引用
- C++指针和引用的语法
- C++处理取消引用语法的泛型类
- 是否可以通过从lambda的引用中返回T型对象,而无需使用尾随返回类型语法
- 以 qreal 引用作为参数的语法
- 利用值类型和引用的统一语法
- 用于在C++中返回引用的语法-与号
- Const引用Visual Studio和GCC之间的语法差异
- C++中的指针和引用变量语法顺序
- 为什么"universal references"具有与右值引用相同的语法?
- 提高精神气-有效引用语法