Why is the copy constructor called when we return an object from a method by value

why is the copy constructor created when we return an object from a method by value. see my code below, in which I return an object from a method, returning a control, clicks on the copy constructor, and then returns. I did not understand the following things:
1) why it calls the copy constructor.
2) which object is passed implicitly to copy the constructor,
3) to which the copy object will copy the content,
4) what is the need to copy the contents of the object during its return. therefore plz help.

#include "stdafx.h" #include <iostream> #include <string> using namespace std; class ClassA { int a, b; public: ClassA() { a = 10; b = 20; } ClassA(ClassA &obj) { cout << "copy constructor called" << endl; } }; ClassA function (ClassA &str) { return str; } int main () { ClassA str; function(str); //function(str); return 0; } 
+4
source share
4 answers

The copy constructor is invoked because you invoke by value not by reference. Therefore, a new object must be created from your current object, since all members of the object must have the same value in the returned instance. Because otherwise you would return the object yourself, which would be returned by reference. In this case, changing the reference object would also change the original. This is usually not the behavior that is required when returning by value.

+1
source

I will try to answer all questions immediately.

The behavior you observe is related to how the object returns by value in C ++. Firstly, the temporary object is copied (or moved to C ++ 11) from the value returned by your function. Then, if this return value is used to initialize another object, for example:

 Class c = fxn(); 

Object c is contour-built (or motion-built, in C ++ 11) from this temporary.

Thus, it is allowed to use elide (in your particular case) or both of these calls for the copy or move constructor in accordance with paragraph 12 / 8.31 of the C ++ 11 standard, although these constructors have side effects and build the return value of the function directly in c :

When certain criteria are met, implementations are allowed to omit the copy / move construction of the object class, even if the constructor selected for the copy / move operation and / or the destructor for the object has side effects . In such cases, the implementation considers the source and purpose of the omitted copy / move as simply two different ways of accessing the same object and the destruction of this object occurs in later times, when two objects would be destroyed without optimization .122 This is the resolution of copy / move operations , called a copy, is allowed in the following cases (can be combined to eliminate multiple copies) :

- in the return expression in a function with the type of the returned class, when the expression is the name of a non-volatile automatic object ( different from the function or catch-clause parameter ) with the same cv-unqualified type as the returned type of the function, the copy / move operation can be omitted during construction an automatic object directly in a function returns a value

- [...]

- if the temporary object of the class that was not attached to the link (12.2) is copied / moved to the class object with the same cv-unqualified type, the copy / move operation can be omitted from building the temporary object directly to the target of the missed copy / move

- [...]

The reason I wrote that in your particular case only one of the calls to the copy or move constructor can be excluded is the sentence in bold in the first brochure of the above Standard Quote:

[...] (except for function parameter or catch-clause) [...]

If you return a parameter to your function, copying elision is prohibited.

Also note that the signature of your constructor should be:

 Class(Class const& c) // ^^^^^ 

There is no reason for you to accept the lvalue reference for non const in the copy constructor, since you are not going to modify the object from which you are copying.

Worse, the above will prevent building a copy from rvalues ​​(e.g. temporary), so the following code will not compile:

 Class foo() { return Class(); } 

Although implementations are allowed to exclude a copy, there must be a viable and affordable copy constructor (or move the constructor if we are talking about relocation).

+12
source

The function returns an object. Therefore, this object must exist. Therefore, this object must be created somewhere. Clearly, this means that one of its constructors should be used. The question is which one?

Since you chose return str; , this is the instruction that will be used to create it. How else could you use this return command to create and return an object, but not use the copy constructor? It is clear that you need to use str to initialize the return value, so you are not going to use another option (constructor without parameters).

+3
source
 ClassA function (ClassA &str) { return str; } 

object str will copy-construct in a temporary object of type ClassA for later use. However, the compiler may omit it due to optimization.

+2
source

Source: https://habr.com/ru/post/1482536/


All Articles