【问题标题】:Is it correct to call std::move on an exception object?在异常对象上调用 std::move 是否正确?
【发布时间】:2022-01-23 21:47:23
【问题描述】:

我很想知道将异常对象移动到某个局部变量是否正确。这个动作有没有可能导致UB?我的担心是由于引用捕获假定访问位于其他地方的异常对象(因为它必须一直存在到堆栈展开结束)。请参见下面的示例。

int main()
{
    std::pair<int,int> res; //may be heavy object, it's only example
    int a[3][5];// assume filled
    try
    {
        for(int i = 0; i < 3; ++i)
        {
            for(int j = 0; j < 5; ++j)
            {
                if(a[i][j] % 2 ==0 )
                {
                    throw std::pair<int,int>(i,j);
                }
            }
        }
    }catch(std::pair<int,int>& pair)
    {
        res = std::move(pair);
    }
}

【问题讨论】:

  • a pair&lt;int,int&gt; 仍然会被复制。
  • 异常不应是“重”对象。
  • 移动一个异常对象很好:结果无论如何都需要是可破坏的,并且在大多数情况下你不会关心对象的状态。当然,如果您打算重新抛出异常,它会将其状态更改为某个不确定的状态(尽管在 std::pair&lt;int, int&gt; 移动对象的情况下不会影响原始对象 - 它将始终被复制)。
  • 虽然我看不出有什么优势,但我认为不会有问题。一点旁注:不应在正常执行流程中抛出异常,而应仅针对罕见的异常事件。
  • 自 C++11 起,捕获异常对象并将其寿命延长到 catch 块之外的标准方法是使用 std::current_exception(),但我看不到任何访问它捕获的对象,您只能使用std::rethrow_exception() 重新抛出它。

标签: c++ c++11 exception raii


【解决方案1】:

移出的对象仍处于有效状态。

即使你通过throw; 重新抛出异常,并再次捕获它,它也会起作用。

对于处于有效但未指定状态的对象(假设您使用这样的对象而不是一对整数),结果可能是意外的,但仍然没有 UB。

【讨论】:

    【解决方案2】:

    由于您的代码没有通过为预期结果抛出异常来遵循良好实践,因此问题的答案实际上并不重要,因为无论如何您都应该重写代码...

    这是一个关于如何编写此类代码的示例。

    #include <utility>
    
    std::pair<int, int> find(int(&a)[3][5])
    {
        for (int i = 0; i < 3; ++i)
        {
            for (int j = 0; j < 5; ++j)
            {
                if (a[i][j] % 2 == 0)
                {
                    return std::pair<int, int>(i, j);
                }
            }
        }
    
        return {};
    }
    
    int main()
    {
        int a[3][5];// assume filled
        auto res = find(a);
    }
    

    虽然您的初始代码可以工作,但抛出和捕获异常可能会很慢,因此即使移动,您的代码也可能比不使用异常返回结果的版本慢。

    一个好的做法是只对意外错误使用异常。

    【讨论】:

      猜你喜欢
      • 2021-08-28
      • 2021-11-02
      • 1970-01-01
      • 2020-11-04
      • 2021-01-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-19
      相关资源
      最近更新 更多