Why do we need a copy constructor for type T?

I am a little vague when a copy constructor is needed. For example, given this function:

template<class T> T max(const T* array, int size) { T result = array[0]; for (int i = 1; i < size; ++i) { if (result < array[i]) { result = array[i]; } } return result; } 

What is the reason why I need a copy constructor for type T ? I think it should be because we are returning by value. This line is T result = array[0]; also needs a copy constructor?

+7
c ++ copy-constructor templates
source share
2 answers

What is the reason I need a copy constructor for type T ?

 T result = array[0]; 

This is called copy initialization and calls the copy constructor for type T Type T will require the creation of a copy constructor for this string.

I think this should be because we are returning a value, so we need a copy constructor for T

 return result; 

For the most part, your guess is true for the return value. However, in this case, the copy constructor is not required. To implement semantics moving , you can implement a moving constructor that eliminates the need for a copy constructor, since the local variable result will be "moved" instead of "copied" from. Moving semantics eliminates the need for unnecessary copies of large objects when they return from a function, since these large objects will not be available after the function returns.

+5
source share

The answer has already been given here:

What is the difference between an assignment operator and a copy constructor?

So, the fact is that:

A copy constructor is used to initialize a previously uninitialized object from some other object data.

Assignment operator used to replace data from a previously initialized object with other object data.

Here is an example:

 #include <iostream> using namespace std; class MyClass{ public: MyClass(){ cout << "Default ctor\n"; } MyClass(const MyClass& copyArg){ cout << "Copy ctor\n"; } MyClass(MyClass&& moveArg){ cout << "Move ctor\n"; } void operator=(const MyClass& assignArg){ cout << "Assignment operator\n"; } bool operator<(const MyClass& comparsionArg) const { return true; } }; template<class T> T max(const T* array, int size) { T result = array[0]; for (int i = 0; i < size; ++i) { if (result < array[i]) { result = array[i]; } } return result; } int main(){ MyClass arr[1]; const MyClass& a = max(arr, 1); return 0; } 

To find out what exactly is going on, we need to compile with -fno-elide-constructors .

Output:

 Default ctor Copy ctor Assignment operator Move ctor 

So, the default constructor is called on this line for one element of the array:

 MyClass arr[1]; 

Then we initialize the previously uninitialized object and the copy constructor :

 T result = array[0]; 

Then we assign a previously initialized object and an assignment operator :

 result = array[i]; 

After we need to create an object outside the scope, as we return by value and for this constructor move :

 return result; 

Then bind the object built with the move constructor in the main scope to const link:

 const MyClass& a = max(arr, 1); 
+1
source share

All Articles