Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why is the move constructor not invoked when returning an rvalue?

I have created a class Animal:

class Animal {
public:
    Animal() = default;
    Animal(Animal&& a) = delete;
    Animal(Animal& a) = delete;

    Animal& operator=(Animal&& a) = delete;
    Animal& operator=(Animal& a) = delete;
};

Animal func1() {
    return Animal();
}

Animal func2() {
    Animal a {};
    return a;
}

int main(void) {
    Animal a1 = func1();
    Animal a2 = func2();
    return 0;
}

I don’t understand why func1() works fine: return Animal() creates an rvalue object and I initialize a1 with this object in the main function; as I see it, it is equal to

Animal a1 = func1()
         ==
Animal a1 = Animal&& temp   //(I wrote type in assignment for clarifying)

and I have read that the return value is an rvalue; however, in func2 I get an error that ‘copy constructor is deleted’ not the move constructor, why?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

Case 1

Here we consider the statement:

 Animal a1 = func1();

The call expression func1() is an rvlalue of type Animal. And from C++17 onwards, due to mandatory copy elison:

Under the following circumstances, the compilers are required to omit the copy and move construction of class objects, even if the copy/move constructor and the destructor have observable side-effects. The objects are constructed directly into the storage where they would otherwise be copied/moved to. The copy/move constructors need not be present or accessible:

  • In a return statement, when the operand is a prvalue of the same class type (ignoring cv-qualification) as the function return type:

That is, the object is constructed directly into the storage where they would otherwise be copied/moved to. That is, in this case(for C++17), there is no need of a copy/move constructor to be available. And so this statement works.

Case 2

Here we consider the statement:

Animal a2 = func2();

Here from non mandatory copy elison,

Under the following circumstances, the compilers are permitted, but not required to omit the copy and move (since C++11) construction of class objects even if the copy/move (since C++11) constructor and the destructor have observable side-effects. The objects are constructed directly into the storage where they would otherwise be copied/moved to. This is an optimization: even when it takes place and the copy/move (since C++11) constructor is not called, it still must be present and accessible (as if no optimization happened at all), otherwise the program is ill-formed:

  • In a return statement, when the operand is the name of a non-volatile object with automatic storage duration, which isn’t a function parameter or a catch clause parameter, and which is of the same class type (ignoring cv-qualification) as the function return type.

That is, the copy/move constructors are required to exist(that is these ctors must be present and accessible) but since you’ve explicitly marked them as deleted this statement fails with the error:

error: use of deleted function ‘Animal::Animal(Animal&&)’

The error can also be seen here

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading