Why is nothing being printed in this example? I'm compiling in Clang on Coliru.
#include <iostream>
struct S
{
S() noexcept = default;
S(S&&) noexcept { std::cout << "move-ctor"; }
};
void f(S) {}
int main()
{
f(S{});
}
A move constructor enables the resources owned by an rvalue object to be moved into an lvalue without copying. For more information about move semantics, see Rvalue Reference Declarator: &&. This topic builds upon the following C++ class, MemoryBlock , which manages a memory buffer.
If you see code that calls std::move() it looks like it should be calling a move constructor, but you could be wrong. When a move constructor on the type being cast to an rvalue does not exist, the compiler will fall back to binding the rvalue as a const-reference. This means the copy-constructor would be used instead.
In general, the compiler should generate move members if you have no user-declared copy members nor destructor. = default and = delete counts as user-declared. If you declare one move member (e.g. move constructor), the other will not be implicitly generated. The compiler will never implicitly delete move members.
Yes, throwing move constructors exist in the wild. Consider std::pair<T, U> where T is noexcept-movable, and U is only copyable (assume that copies can throw). Then you have a useful std::pair<T, U> move constructor which may throw.
The compiler is performing copy elision, which is allowed per paragraph 12.8/31 of the C++11 Standard even if your move constructor, copy constructor, or destructor have side effects:
When certain criteria are met, an implementation is allowed to omit the copy/move construction of a class object, even if the constructor selected for the copy/move operation and/or the destructor for the object have side effects.
The term copy elision is used even when a move is being elided:
This elision of copy/move operations, called copy elision, is permitted in the following circumstances (which may be combined to eliminate multiple copies):
[...]
— when a temporary class object that has not been bound to a reference (12.2) would be copied/moved to a class object with the same cv-unqualified type, the copy/move operation can be omitted by constructing the temporary object directly into the target of the omitted copy/move
[...]
With GCC, you can use the -fno-elide-constructors
to inhibit copy elision. In this case, you would see that the move constructor gets invoked, as in this live example.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With