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.