Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/visual-studio-2010/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;捕获块-按值或引用捕获异常?_C++_Exception Handling - Fatal编程技术网

C++ C++;捕获块-按值或引用捕获异常?

C++ C++;捕获块-按值或引用捕获异常?,c++,exception-handling,C++,Exception Handling,可能重复: 我总是通过值捕捉异常。e、 g try{ ... } catch(CustomException e){ ... } 但是我遇到了一些代码,这些代码使用了catch(CustomException&e)。这是a)精细b)错误c)灰色区域吗?如果异常是派生类型,则按值捕获会将异常对象切片为您捕获的类型 对于catch块中的逻辑来说,这可能很重要,也可能不重要,但是没有什么理由不通过const引用捕获 请注意,如果您抛出 catch块中没有参数,则原异常被重新抛出,无论您是否捕获了切

可能重复:

我总是通过值捕捉异常。e、 g

try{
...
}
catch(CustomException e){
...
}
但是我遇到了一些代码,这些代码使用了
catch(CustomException&e)
。这是a)精细b)错误c)灰色区域吗?

如果异常是派生类型,则按值捕获会将异常对象切片为您捕获的类型

对于catch块中的逻辑来说,这可能很重要,也可能不重要,但是没有什么理由不通过const引用捕获


请注意,如果您
抛出 catch块中没有参数,则原异常被重新抛出,无论您是否捕获了切片副本或引用异常对象。

< P> C++中异常的标准实践是…

按值抛出,按引用捕获


在继承层次结构中,按值捕获是有问题的。假设您的示例中有另一个类型
MyException
,它继承自
CustomException
,并像错误代码一样覆盖项目。如果抛出了
MyException
类型,则catch块将导致它转换为
CustomException
实例,从而导致错误代码更改

除非您想处理异常,否则通常应该使用const引用:
catch(const CustomException&e){…}
。编译器处理抛出对象的生存期。

(CustomException e)
中创建CustomException的新对象。。。因此,在(CustomException&e)中调用它的构造函数时,它将只调用引用。。。未创建新对象,也不会调用构造函数。。。所以正式是一点点开销。。。稍后最好使用…

我将添加:catch by const reference。不幸的是,您可以抛出一个常量对象,并使用非常量引用捕获它。为了避免这种沉默的常量“丢弃”,请始终捕获一个常量引用,并确保您的异常类型具有正确的常量访问器。@Danial Earwicker:为什么通过非常量引用捕获会“不幸”?异常对象总是被复制的,所以无论抛出什么“对象”,都不能从任何catch块影响原始对象,因为抛出的“对象”实际上只是一个初始值设定项。康斯特是无法摆脱的;异常对象总是非常量、非易失性的。允许通过非常量引用捕获允许中间捕获块向异常添加信息。它不常用,但如果您需要它,它就在那里。@John:第15章异常,特别是第15.3章(异常处理)描述了如何从异常对象初始化catch参数。当参数是类类型(而不是引用)时,它是通过复制构造函数初始化的。@Daniel:为了澄清Charles(并传递到您的收件箱),根据定义,您可以捕获并重新引用的异常对象是临时的。
throw
的参数应该在堆栈上,并且应该作为展开业务的第一个顺序被销毁<代码>扔掉新的
是一个错误。@Charles-你说得对,它并不是真的扔掉常量。我想我认为它与通过非常量引用传递给方法的临时方法是一样的,非常量引用在语言的其他地方被禁止,以避免试图通过引用对临时方法进行变异(当变异无论如何都将被丢弃时)。但是正如您所说的,您可能希望故意改变异常,然后抛出
throw使它在其他地方可见(从而打破了我的类比)。我不熟悉这个上下文中的术语slice。我认为“slice”是一个习惯于引用传递语言的人喜欢使用的术语。其思想是,如果将派生对象分配给其基类型,则可以“切掉”对象的一部分,这对我来说似乎是一种误导,因为实际发生的是在基类的复制赋值操作符
base&operator=(const base&other)中
派生对象被隐式转换为
基类&
引用,因此赋值将派生类视为基类。没有神奇的切片或转移东西,你称之为function@Injektilo我认为slice主要关注虚拟函数。您可以使用基类引用来捕获派生类异常对象,因此动态绑定在这里非常有用。对于按值捕获,基类对象将丢失派生类详细信息;对于按引用捕获,派生类信息仅隐藏。请注意,正确的引用也是常量:
catch(CustomException const&e)
…不应标记为重复--通过ptr捕获异常与通过引用或值捕获不同。密切相关且有用:在引用场景中,e的内存是如何释放的?如果e在堆栈中,则catch块变为无意义?