【问题标题】:Throw exception by value or reference按值或引用抛出异常
【发布时间】:2016-04-20 08:55:37
【问题描述】:

来自这个答案https://stackoverflow.com/a/36738405/4523099:

没有操作数的 throw 表达式重新抛出当前处理的 例外。使用现有临时重新激活异常; 没有创建新的临时异常对象。 -- ISO/IEC 14882:2011 第 15.1 节。 8

那么为什么我会从这段代码中得到这个结果呢?

代码:

#include <iostream>

class my_exception: public std::exception{
public:
    int value;
};
int main()
{
    my_exception ex;
    ex.value=1;
    try{
        throw ex;
    }
    catch(my_exception& e){
        e.value=2;
    }
    std::cout << ex.value;
   return 0;
}

实际结果:

1

我认为应该是 2,具体取决于标准配额。我错过了什么?

【问题讨论】:

  • “没有操作数的 throw 表达式” 是 throw;(在 catch 块中)。

标签: c++ c++11 exception throw


【解决方案1】:

这是因为 throw(普通版)将 make a copy :

首先,从表达式复制初始化异常对象(这可能会调用右值表达式的移动构造函数,并且复制/移动可能会受到复制省略),...

并将其保留在内部,因此e.value=2; 会修改内部副本。

在 SO 中,您提到的问题是关于重新抛出的版本,女巫不会制作新副本,而是使用已经存在的内部副本。

【讨论】:

    【解决方案2】:

    只有重新抛出(没有操作数)才能重用同一个异常对象。下面是一些代码来证明这一点:

    #include <iostream>
    
    class my_exception: public std::exception{
    public:
        int value;
    };
    
    void f(my_exception& ex) {
        ex.value = 1;
        try {
            throw ex;
        } catch (my_exception& e) {
            e.value = 2;
            // Here's the re-throw
            throw;
        }
    }
    
    int main()
    {
        my_exception ex;
        try {
            f(ex);
        } catch (my_exception& e) {
            std::cout << e.value;
        }
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 2023-03-11
      • 2021-04-29
      • 2022-01-05
      • 1970-01-01
      • 2011-10-12
      • 2011-08-29
      • 2013-05-24
      • 2011-06-02
      • 1970-01-01
      相关资源
      最近更新 更多