3

As the subject,the related code is:

#include <iostream>     

class ABC     
{  public:  
    ABC() 
    {
        std::cout<< "default construction" << std::endl;
    }

    ABC(const ABC& a) 
    {
        std::cout << "copy construction" << std::endl;
    } 

    ABC(const ABC&& a) 
    {
        std::cout << "move construction" << std::endl;
    }
};                         

int main()   
{  
   ABC c1 = ABC();  

   return 0;  
}

Output with -fno-elide-constructors -std=c++11

default construction
move construction

If i remove the move constructor above, then the output is:

default construction
copy construction

why copy construction could be used while move constructor has been removed?You see, if there is a user defined move constructor, the compiler prefer to use move constructor.

As per some documentation,compiler provides a default move constructor.**So why don't the compiler use the default move constructor? I am a novice in C++.I would be grateful to have some help with this question.

sunshilong369
  • 646
  • 1
  • 5
  • 17
  • 2
    `ABC(const ABC&&)` is not a move ctor. Remove the const: `ABC(ABC&&)`. – besc May 30 '20 at 07:35
  • @Thank you.Could you explain that in more detail?I am a little confused since this code(remove keyword `const`)[https://godbolt.org/z/YAwdMo] could compile indeed. – sunshilong369 May 30 '20 at 07:53
  • Seems I was wrong. Cppreference says that `T(const T&&)` *does* count as a move ctor. Anyway. Start with reading [cppreference: rule of five](https://en.cppreference.com/w/cpp/language/rule_of_three), then follow the links to the dedicated ctor/assignment pages. – besc May 30 '20 at 08:15
  • @besc Do you think `T(T&&)` (no keyword `const`) count as a move ctor? – sunshilong369 May 30 '20 at 08:56

1 Answers1

5

As per some documentation,compiler provides a default move constructor.

Let's take a look at some documentation. The following is from cppreference.com.

If [conditions] then the compiler will declare a move constructor as a non-explicit inline public member of its class with the signature T::T(T&&).

You're right. The compiler does provide a defualt move constructor under the right conditions. However, those conditions are important. The first condition you seem to be aware of: there cannot be a user-defined move constructor. So that just leaves this list of conditions:

  • there are no user-declared copy constructors;
  • there are no user-declared copy assignment operators;
  • there are no user-declared move assignment operators;
  • there is no user-declared destructor;

And there you go. Your user-defined copy constructor is preventing the compiler from providing a default move constructor. Hence there is no move constructor to use.

JaMiT
  • 14,422
  • 4
  • 15
  • 31
  • Thank you for the clarification.Then why `copy construction` could be used while `move constructor` has been removed?You see, if there is a user defined `move constructor`, the compiler prefer to use `move constructor`. – sunshilong369 May 30 '20 at 05:16
  • If the ```move ctor``` is unavailable, the ```copy ctor``` is selected via normal function matching. The ```const ABC&``` can bind to the temporary created with ```ABC()```. In presence of ```move ctor```, ```ABC&&``` is better match since no ```const conversion``` is needed. @sunshilong369 – User 10482 May 30 '20 at 06:15
  • @User10482 Thank you for the clarification.Is it(The const ABC& can bind to the temporary created with ABC().) granteed by C++ standard?One more question, why compiler complains when `ABC(const ABC&)` is replaced by ` ABC(ABC&)` ? – sunshilong369 May 30 '20 at 07:44
  • @sunshilong369 Right, the compiler *prefers* to use the move constructor over the copy constructor. However, it has an even stronger preference to use something that exists over something that does not. The copy constructor does fit this use, just not as well as the move constructor. – JaMiT May 30 '20 at 13:27
  • @sunshilong369 Your construction starts with a temporary `ABC` object that is then transferred (moved or copied) to another object. That is, the parameter to the move or copy constructor is a temporary object. So asking about `ABC(ABC&)` is close to asking [How come a non-const reference cannot bind to a temporary object?](https://stackoverflow.com/questions/1565600/how-come-a-non-const-reference-cannot-bind-to-a-temporary-object) – JaMiT May 30 '20 at 13:30
  • @JaMiT Glad to see you again.Thank you for the clarification.I would see it right away. – sunshilong369 May 30 '20 at 14:09