捕获异常时,标准指导是按值抛出,通过引用捕获.据我了解,这有两个原因:
如果我们有一个我们没有在catch块中定义异常名称的场景,那么这些问题(实际上是1.,因为如果我们没有变量的名称,切片不会成为问题)仍然有效吗?
例如:
catch(my_exception)
{ ... }
Run Code Online (Sandbox Code Playgroud)
要么
catch(my_exception &)
{ ... }
Run Code Online (Sandbox Code Playgroud)
如果在这种情况下由值捕获的异常,是否仍有可能终止程序?我的感觉是技术上仍然可行.
注意:我问这个是因为我必须审查某人的代码,在这种情况下按值放置.如问题中所示,我不完全确定任何一种选择的技术影响,但我认为就整体而言,最好在这种情况下通过引用而不管(在任何情况下都没有通过引用捕获的缺点) .
在未命名的异常对象的情况下,该标准不需要特殊优化.相反,它需要一个效果,好像临时是复制初始化.此复制可能导致内存被动态分配.
N3290§15.3/ 16:
如果异常声明指定了一个名称,它声明一个从异常对象复制初始化(8.5)的变量.如果exception-declaration表示对象类型但未指定名称,则从异常对象复制初始化(8.5)临时(12.2).在处理程序中初始化的任何自动对象的销毁之后,处理程序退出时变量或临时的生命周期结束.
上面的段落没有提到引用,因此可以合理地得出结论,无论异常对象是否被引用捕获,它都适用; 无论如何都要构建一个副本.
但是,这与下一段相矛盾:
N3290§15.3/ 17:
当处理程序声明一个非常量对象时,对该对象的任何更改都不会影响通过执行throw-expression初始化的临时对象.当处理程序声明对非常量对象的引用时,对引用对象的任何更改都是对执行throw-expression时初始化的临时对象的更改,并且如果该对象被重新抛出则会生效.
因此,声明的类型T&(带有T非const)是C++ 11需要直接引用抛出对象而不是复制的单一情况.在C++ 03中也是这样,除了C++ 03有一些关于as-if优化的附加措辞.因此,对于正式,首选应该是
catch( T& name )
Run Code Online (Sandbox Code Playgroud)
和
catch( T& )
Run Code Online (Sandbox Code Playgroud)
但是,我总是遇到例外情况catch( T const& ).从实际的角度来看,可以假设编译器将优化它以直接引用抛出的对象,即使可以设计观察到的程序效果将是非标准的情况.例如<evil grin>
#include <stdio.h>
#include <stdexcept>
struct Error
: std::runtime_error
{
public:
static Error* pThrown;
char const* pMessage_;
Error()
: std::runtime_error( "Base class message" )
, pMessage_( "Original message." )
{
printf( "Default-construction of Error object.\n" );
pThrown = this;
}
Error( Error const& other )
: std::runtime_error( other )
, pMessage_( other.pMessage_ )
{
printf( "Copy-construction of Error obejct.\n" );
}
char const* what() const throw() { return pMessage_; }
};
Error* Error::pThrown = 0;
int main()
{
printf( "Testing non-const ref:\n" );
try
{
throw Error();
}
catch( Error& x )
{
Error::pThrown->pMessage_ = "Modified message.";
printf( "%s\n", x.what() );
}
printf( "\n" );
printf( "Testing const ref:\n" );
try
{
throw Error();
}
catch( Error const& x )
{
Error::pThrown->pMessage_ = "Modified message";
printf( "%s\n", x.what() );
}
}
Run Code Online (Sandbox Code Playgroud)
使用MinGW g ++ 4.4.1和Visual C++ 10.0,输出是......
Testing non-const ref: Default-construction of Error object. Modified message. Testing const ref: Default-construction of Error object. Modified message
一个迂腐的形式主义者可能会说两个编译器都不符合规定,没有为Error const&案例创建副本.一个纯粹实际的从业者可能会说嘿,你还期待什么?而我,我说标准中的措辞在这里非常完美,如果有的话,人们应该期望澄清明确允许上面的输出,以便通过引用捕获const既安全又最有效.
总结一下.OP的问题:
通过引用捕获不会调用可能会终止程序的复制构造函数.
该标准仅保证此参考非const.
实际上,如图所示,const即使计划结果受到影响,也可以保证参考.
干杯&hth.,
| 归档时间: |
|
| 查看次数: |
3279 次 |
| 最近记录: |