为什么C++异常(可能)被复制
Why are C++ exceptions (potentially) copied
从这个答案和类似的页面中,我了解到异常可能在抛出过程中被复制。我还了解到,这个复制不能抛出任何额外的异常,否则会调用std::terminate()
。这使得编写异常类变得困难,因为例如std::string
在被复制时可能引发异常。
我的问题是:为什么C++允许编译器复制异常?通过引用或指针抛出它们,并要求程序员通过引用或指示器而不是通过值来捕获它们,这样做的缺点是什么?
解决方案似乎是将任何非平凡的成员封装在类似std::shared_ptr
的东西中,并复制该指针而不是它所包含的对象。但是,我们失去了复制的所有潜在优势(例如,您可以在原始保持不变的情况下编辑副本(。那么,为什么C++坚持要能够复制异常呢?
根据对我的问题的评论,我认为这或多或少地回答了它(尽管我的措辞可能不准确(:
为什么允许复制异常
大多数异常都是由值抛出的,即
throw my_exception("This is wrong!);
而不是像那样抛出指针
throw new my_exception("This is wrong!);
当异常由值引发时,它会被分配到堆栈上,并且由于堆栈将被展开,因此必须复制才能将其传播到堆栈上。
因此,如果标准不要求异常是可复制的,那么就必须要求所有异常都作为指向堆分配对象的指针抛出。但正如Sam Varshavchik指出的那样,这增加了一些通常不需要的开销。异常通常是小对象,因此复制它们会比在堆上分配和释放它们带来更少的开销。
问题并不像看上去那么大
正如formerlykknownas_463035818所指出的,大多数程序员不应该担心在复制另一个异常时出现内存不足异常(bad_alloc
(。如果内存太满,以至于没有空间容纳异常的副本,那么程序几乎肯定很快就会崩溃。
然而,重要的是要以这样一种方式写入异常,即它们的复制构造函数不会抛出所有其他类型的异常,因为这会终止程序,而它可能已经能够捕获原始异常并从中恢复。
- 有可能在Armadillo中复制MATLAB circshift方法吗
- 使用仅使用一次的变量调用的复制构造函数.这可能是通过调用move构造函数进行编译器优化的情况吗
- 为什么C++异常(可能)被复制
- 是否有可能在没有复制的情况下传递 std::vector<int> 作为参数来获得 std::vector<std::array<int, 3>>?
- 2 个默认的复制构造函数:可能吗
- 包装二进制缓冲区 - 可能没有多余的移动/复制?
- 如果可能,C++按右值引用传递参数,否则复制左值引用
- 深层复制(可能与指针有关)
- 在低级别实现交换复制位时可能会出现什么问题
- 重载运算符 = 返回 void 是否不可能成为复制赋值运算符
- 对于不可复制类型的范围循环,是否可能
- 复制构造函数中出现异常的可能原因是什么
- 通过添加指针进行复制时可能出现缓存未命中
- 在取消定义宏函数之前,在宏函数中使用/复制宏变量的值:可能吗?
- 为什么我遇到此代码的分段错误?此代码几乎没有运行,因此构造函数或复制构造函数中可能存在错误
- 在可能重叠的范围之间复制类
- C++:存储复制操作不合理或不可能的资源
- 琐碎的可复制性和可能不可复制性的价值表达之间有显著差异吗
- 有没有可能在不复制的情况下使特征矩阵变平
- 我无法追踪可能的复制构造错误