There is a copy constructor:

Implementation(const Implementation & other) : Implementation(other.clone()) {} 

And there is a clone() function:

 Implementation Implementation::clone() const { return Implementation(this->number(), this->string(), this->vector()); } 

Motion Designer:

 Implementation( Implementation && other) noexcept : Implementation() { this->swap(other); } 

I do not understand why the move constructor is not called in the string Implementation(other.clone()) (the motion constructor is defined). After all, the clone() function returns just a copy of the object for which it is called. What is called?

    1 answer 1

    The compiler has the full right to apply copy elision , that is, to replace the movement with the construction of the object directly at the place of its further assignment.

    To confirm my words, I used the online compiler :

    Source:

     #include <string> #include <vector> class Implementation { private: int number() const; std::string string() const; std::vector<int> vector() const; public: Implementation(); Implementation(int, std::string, std::vector<int>); Implementation(const Implementation & other); Implementation(Implementation && other) noexcept; Implementation clone() const; void swap(Implementation& other); }; Implementation::Implementation(const Implementation & other) : Implementation(other.clone()) {} Implementation Implementation::Implementation::clone() const { return Implementation(this->number(), this->string(), this->vector()); } Implementation::Implementation(Implementation && other) noexcept : Implementation() { this->swap(other); } 

    The compiled result of the function of interest to us in the Intel x86_64 assembly language:

     Implementation::Implementation(Implementation const&): push rbp mov rbp, rsp sub rsp, 16 mov QWORD PTR [rbp-8], rdi mov QWORD PTR [rbp-16], rsi mov rax, QWORD PTR [rbp-8] mov rdx, QWORD PTR [rbp-16] mov rsi, rdx mov rdi, rax call Implementation::clone() const nop leave ret 

    As you can see, the compiler really applied the technique I specified. The this pointer is passed through the register (E/R)CX . That is, Implementation::Implementation(Implementation const&) as it took this (in the case of the constructor, it points to an uninitialized memory area for the object), and passes it on to clone() without any modifications.

    • I noticed that if you add std::move to the specified line, then the call of such to-ra will happen. It turns out such an addition prohibits the compiler to carry out a similar optimization? - Jenssen
    • @Jenssen, yes, by explicitly using std::move() you tell the compiler that you just need to move, with the obligatory call of your constructor (which may be interacting with the operating system, for example). And yet, I added the answer. - ߊߚߤߘ