Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is the move-constructor not called?

Tags:

c++

c++11

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{});
}
like image 265
user2030677 Avatar asked Jun 01 '13 12:06

user2030677


People also ask

What is a move constructor?

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.

Does STD move call constructor?

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.

Does compiler generate move constructor?

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.

Can move constructor throw?

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.


1 Answers

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.

like image 99
Andy Prowl Avatar answered Sep 22 '22 13:09

Andy Prowl