C++异常捕获子句
C++ exceptions catch clause
可能重复:
C++中异常对象的范围
我有以下捕获条款:
catch(Widget w);
catch(Widget& w);
void passAndThrowWidget() {
Widget localWidget;
throw localWidget;
}
若我们通过值捕获Widget对象,编译器将进行复制,所以当我们抛出异常时,localWidget超出了范围,我们并没有看到任何问题。
若我们通过引用捕获widget对象,根据引用的概念,"w"指向相同的本地widget,而不是副本。但我看到大多数异常都是由C++中的引用捕获的。我的问题是,当抛出异常并通过引用捕获指向被销毁的对象时,"localWidget"是如何工作的就超出了范围。
谢谢!
throw expr;
与return expr;
的相似之处在于,它使用复制初始化(列表初始化也可以使用C++0x(。但这(主要(是语法。
当涉及到语义时,就像从返回非引用类型的函数返回值一样,抛出也是可以的:
T f()
{
// t is local but this is clearly fine
T t;
return t;
// and so is this
throw t;
}
此外,还未指定返回或抛出的内容是return
或throw
语句的表达式的结果,还是该表达式的副本(或移动(。
通过引用捕获的通常动机与生存期无关——抛出对象的生存期保证至少与catch子句一样长。它是优选的,因为它允许以多形态设计和使用异常。
C++运行时使用独立于堆栈的内存位置来存储异常对象:
2.4.2分配异常对象
例外情况需要存储抛出。此存储必须持久当堆栈正在展开时,因为它将由处理程序使用,并且必须确保线程安全。异常对象因此,存储通常在堆中分配,尽管实现方式可以提供支撑投掷的应急缓冲装置内存不足时的
bad_alloc
异常条件(见第3.3.1节(。
(来自安腾C++ABI:异常处理(
因此,当你";引用捕获";是对该内存位置的引用,而不是对已释放堆栈帧的引用。这意味着异常对象可以保证生存足够长的时间,以便异常处理程序使用,即使是通过引用获得的。(不过,一旦你离开catch范围,它们可能会被释放,所以不要抓住异常引用。(
异常是本地作用域规则的异常:
try
{
Widget w;
throw w;
}
catch (const Widget& exc)
{
// exc is a valid reference to the Widget
}
即使本地作用域已经结束,也会以特殊的方式处理异常,因此抛出的内容仍然可以访问。
在这一行中,您正在创建本地对象的副本
throw localWidget;
因此,它不是指您的本地"localWidget"对象,而是该对象的副本(称为exception-object(,它保证在catch子句完全处理异常之前一直有效。
抛出的实例在抛出时被复制。所以你无论如何都会得到一份。
最好通过引用捕获,因为抛出的对象可能是多态的,并且您不希望依赖于多态类的副本生成的"错误代码"。"错误代码"不会特定于在抛出点抛出的派生类。
- 处理多个异常集合的C++方法
- 我在c++代码中生成了一个运行时#3异常
- 孤立代码块在结构中引发异常
- 如何理解C++标准N3337中的expr.const.cast子句8
- C++中的赋值发生,尽管右侧出现异常
- 从构造函数抛出异常时如何克服内存泄漏
- 异常属于C++中的线程还是进程
- 当类定义不可见时捕获异常
- 引发异常:读取访问冲突**dynamicArray**为0x1118235.发生
- 为什么异常不退出程序?
- 为什么我应该在异常处理中使用std::cerr而不是std::cout
- 如何修复链表类实现的未处理异常0xDDDDDDDD
- 关于:C++中异常对象的范围:为什么我没有得到副本?
- 是什么导致了Unity 3D中的"错误线程异常"?
- 如何将strftime中的格式错误作为异常捕获
- 创建具有 new in 函数和"this is nullptr"异常的对象
- 尝试使用智能指针时引发异常
- 为什么派生类异常可以被基类捕获子句捕获
- 在交换机的默认子句中抛出自定义异常会生成单个字符
- C++异常捕获子句