对异常对象调用std::move是否正确



我很想知道将异常对象移动到某个局部变量是否正确。这一行动是否有可能导致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);
}
}

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

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

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

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

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

#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);
}

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

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

最新更新