http://www.drdobbs.com/cpp/practical-c-error-handling-in-hybrid-env/197003350?pgno=4
In this article Herb Sutter explains that throwing an exception requires a copy
Move from exception objects is not mandatory now.
It's a defect of C++11. See CWG1493 .
But modern C++ provides more feature: "Moving safely with move semantics & exception"
struct demo
{
demo() = default;
demo(const demo &) { cout << "Copying\n"; }
// Exception safe move constructor
demo(demo &&) noexcept { cout << "Moving\n"; }
private:
std::vector<int> m_v;
};
int main()
{
demo obj1;
if (noexcept(demo(std::declval<demo>()))){ // if moving safe
demo obj2(std::move(obj1)); // then move it
}
else{
demo obj2(obj1); // otherwise copy it
}
demo obj3(std::move_if_noexcept(obj1)); // Alternatively you can do this----------------
return 0;
}
noexcept(T(std::declval<T>()))
to check if T
’s move constructor exists and is noexcept
in order to decide if we want to create an instance of T
by moving another instance of T
(using std::move
). std::move_if_noexcept
, which uses noexcept
operator and casts to either rvalue or lvalue. Such checks are used in std::vector
and other containers.std::move_if_noexcept
which will move ownership of critical data only and only if move constructor is exception-safe.From: 7 best practices for exception handling in C++
I have just checked, and the Standard allows
Since these omissions are allowed, the spec requires to first regard the source of the copy or move as an rvalue. So this means that the respective objects will be moved if possible. Of course copy and move elision are still allowed as the first choice.
I was notified that the consideration of the exception object initializer of a catch clause parameter as an rvalue initializer will probably be dropped from the Standard (because in general it is not possible for all cases to detect when the behavior of the program is unchanged when omitting a copy/move), so I recommend to not rely on this (second bullet above).
What you can still rely about is the move of a local variable into the exception object, as in throw x;
(first bullet above).