Home > database >  Should explicit keyword be used for move constructors?
Should explicit keyword be used for move constructors?

Time:02-05

This code does not compile. But if I remove the explicit keyword from the move constructor then it works. Why?

struct Bar {
    Bar() {}
    explicit Bar(const Bar& x) {}
    explicit Bar(Bar&& x) {}
};

Bar bar() {
    Bar x;
    return x;
}

The compilation error is:

error: no matching function for call to 'Bar::Bar(Bar&)'

CodePudding user response:

The return statement copy-initializes the return value from the operand.

Copy-initialization doesn't consider explicit constructors. But explicit doesn't change that the constructors you defined are copy and move constructors. Therefore no other implicit constructors will be declared.

In effect, there is no viable constructor left to construct the return value.

If you remove the explicit on either of the constructors, there will be a viable constructor to construct the return value and it will compile. The move constructor will be preferred if it is not explicit, because of the special semantics of return statements.


Copy and move constructors should usually not be explicit.

CodePudding user response:

Typically, no. Do you want move-construction to be explicit? If so, yes. Otherwise: no. But typically only converting constructors are explicit. (I occasionally make the copy-c'tor explicit, delete the copy-assignment operator, but leave the move-c'tor implicit when I have a "heavy" class that almost never want to deeply-copy, so users can say Foo(foo) if they want a copy, but they have to think about it.)

CodePudding user response:

return x; performs copy initialization, which won't consider explicit constructors.

Copy-initialization is less permissive than direct-initialization: explicit constructors are not converting constructors and are not considered for copy-initialization.

BTW for the return statement like return x;, the move constructor of Bar will be considered firstly; then the copy constructor if the move constructor is not appropriate.

  •  Tags:  
  • Related