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?
>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