I am interested to know if is it correct to move an exception object to some local variable. Is there any possibility for this action to lead into UB? My concerrns are due to the fact that catching by reference assumes access to exception object, which is located in other place (because it must live until the end of the stack unwinding). See example below.
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);
}
}
CodePudding user response:
Moved-out object is still in a valid state.
Even if you rethrow the exception via throw;
, and catch it again, it will work.
The result might be unexpected for an object left in a valid-but-unspecified state (assuming you use such an object instead of a pair of ints), but still no UB.
CodePudding user response:
As your code does not follows good practice by throwing an exception for an expected result, it really does not matter much the answer of the question as your should rewrite your code anyway...
Here is an example on how you could write such code.
#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);
}
While your initial code would works, throwing and catching exception could be slow thus even with moving, your code might be slower that a version that do not use exception to return the result.
A good practice is to use exception only for unexpected errors.