C++ 在catch-block-exception中毫无意义地使用引用传递语法?

C++ 在catch-block-exception中毫无意义地使用引用传递语法?,c++,exception,pass-by-reference,C++,Exception,Pass By Reference,我的示例代码: #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;

我的示例代码:

#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。当您的异常处于继承继承继承权中时,它还可以防止切片。有时,人们在将异常对象重新抛出到调用作用域之前使用它来变异异常对象,尽管这似乎是罕见的


通过引用const捕获它与通过引用const捕获任何其他事物具有相同的好处:它确保您不会变异异常。如果您不重新引用它,那么这里就没有实际的好处,但是如果您像我一样,在默认情况下编写const作为防止错误的故障保护,那么就没有理由不使用它。

您是通过引用捕获异常对象,而不是将其本身抛出

异常总是按值抛出的,因为它们必须分配到进程内存的一个特殊区域,该区域不受堆栈展开的影响

[C++14:15.1/3]:抛出异常副本会初始化8.5、12.8临时对象,称为异常对象。临时变量是一个左值,用于初始化匹配处理程序15.3中声明的变量。[……]

这是一条通用规则,旨在解释更常见的情况,即T实际上是try块本身或其封装函数的局部。如果不复制它,就不可能从调用作用域捕获它

这样,您就不会不必要地再次复制已复制的t。当您的异常处于继承继承继承权中时,它还可以防止切片。有时,人们在将异常对象重新抛出到调用作用域之前使用它来变异异常对象,尽管这似乎是罕见的

通过引用const捕获它与通过引用const捕获任何其他事物具有相同的好处:它确保您不会变异异常。如果您不重新引用它,那么这里就没有实际的好处,但是如果您像我一样,默认情况下编写const作为防止错误的故障保护,那么就没有理由不使用它

“为什么T对象在捕捉块之后仍然打印100

因为抛出是按值进行的,所以创建一个副本

“在这种情况下,引用语法在传递值上有什么用途

没什么

参考便秘是一个很好的经验法则,因为它通常是有效和安全的

上面的代码,就像我写这篇文章时的代码一样,不能通过引用const来捕获,所以这只是一个很好的实践

顺便说一句,谈到良好的实践,使用所有大写名称有可能与宏名称发生冲突,在这种情况下,会误导训练有素的读者使用宏

单字母大写名称,尤其是T,在某种程度上是一种特殊情况,因为按照惯例,它们被用于模板参数,所以它们不太可能被用作宏名称

尽管如此,我还是推荐旧的约定,宏都是大写的,总是大写的,其他的都是混合或小写的

1一度,C++98和C++03标准的措辞可以解释为仅通过引用非常量保证的效率进行捕获。这是一个独特的解释,但至少有一个著名的C++人提倡。它现在只是具有历史意义。

“为什么T对象在捕捉块之后仍然打印100

因为抛出是按值进行的,所以创建一个副本

“在这种情况下,引用语法在传递值上有什么用途

没什么

参考便秘是一个很好的经验法则,因为它通常是有效和安全的

上面的代码,就像我写这篇文章时的代码一样,不能通过引用const来捕获,所以这只是一个很好的实践

顺便说一句,谈到良好的实践,使用所有大写名称有可能与宏名称发生冲突,在这种情况下,会误导训练有素的读者使用宏

单字母大写名称, 特别是T,在某种程度上是一个特例,因为按照惯例它们被用于模板参数,所以它们不太可能被用作宏名称

尽管如此,我还是推荐旧的约定,宏都是大写的,总是大写的,其他的都是混合或小写的

1一度,C++98和C++03标准的措辞可以解释为仅通过引用非常量保证的效率进行捕获。这是一个独特的解释,但至少有一个著名的C++人提倡。它现在只是具有历史意义。

请参见“为什么按引用捕获”:不要对控制流使用异常,而是按其本意对异常情况使用异常。请参见“为什么按引用捕获”:不要对控制流使用异常,而是按其本意对异常情况使用异常。如果它是按值传递的,为什么我们必须使其为常量。我们无论如何都不能修改实际对象,用常量引用而不是非常量引用捕获有什么好处?人们经常声称这一点,但没有人能够证明这一点,而是挥手说efficiency@InQusitive:是的,你可以。你可以对它进行变异并重新命名。你不能修改原始对象,但那几乎无关紧要。@MattMcNabb:就我个人而言,我看不到。我这样做只是因为我默认使用const。你能举一个可能出现问题的例子吗?如果它是按值传递的,为什么我们必须使它为const。我们无论如何都不能修改实际对象,用常量引用而不是非常量引用捕获有什么好处?人们经常声称这一点,但没有人能够证明这一点,而是挥手说efficiency@InQusitive:是的,你可以。你可以对它进行变异并重新命名。你不能修改原始对象,但那几乎无关紧要。@MattMcNabb:就我个人而言,我看不到。我这样做只是因为我默认使用const。你能举一个可能出现问题的例子吗?