问题
Especially in connection with std::vector
it is important that types are noexcept
movable when possible.
So when declaring a move constructor = default
like in
struct Object1
{
Object1(Object1 &&other) = default;
};
std::is_nothrow_move_constructible<Object1>::value
will be true
as every member (0 here) of Object1
is nothrow-move-constructible, which is answered here.
Yet what happens if the move copy constructor is only declared and then later = default
defined like in the following code?
struct Object2
{
Object2(Object2 &&other);
};
Object2::Object2(Object2 &&other) = default;
With g++ 4.9.2 std::is_nothrow_move_constructible<Object2>::value
is false
and I have to mark both the declaration and the definition as noexcept
to make it true
.
Now what I am interested in is what the actual rules are.
Especially since Item 22 in Effective Modern C++ (Scott Meyers) seems to give ill advice by suggesting to implement the pimpl-idiom move constructor like I did with Object2
.
回答1:
[dcl.fct.def.default]/p2:
If a function is explicitly defaulted on its first declaration,
- it is implicitly considered to be
constexpr
if the implicit declaration would be, and,- it has the same exception specification as if it had been implicitly declared (15.4).
These rules do not apply if the function is explicitly defaulted on a later declaration, as in your later example, so instead, except for destructors, the function is considered noexcept(false)
by default like most other functions.
Since the explicit defaulting can be in a different translation unit - and in the pimpl case, is in a different TU - there's no general way for the compiler to figure out after seeing the class definition only whether the move constructor will throw, unless the function is explicitly defaulted in the class definition (i.e., at its first declaration).
来源:https://stackoverflow.com/questions/28660945/what-are-the-rules-for-noexcept-on-default-defined-move-constructors