Reputation: 586
I am a little uncertain when the 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 that I need a copy constructor for the type T
? I think it must be because we return by value. Does this line T result = array[0];
also need the copy constructor?
Upvotes: 4
Views: 589
Reputation: 1246
This was already answered here:
What's the difference between assignment operator and copy constructor?
So the thing is:
A copy constructor is used to initialize a previously uninitialized object from some other object's data.
An assignment operator is used to replace the data of a previously initialized object with some other object's data.
Here's 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 see what's exactly happening we need to compile with -fno-elide-constructors
.
The output is:
Default ctor
Copy ctor
Assignment operator
Move ctor
So here, the default constructor is called at this line for one element of array:
MyClass arr[1];
Then we initialize a previously uninitialized object and copy constructor is called:
T result = array[0];
Then we make an assignment to previously initialized object and assignment operator called:
result = array[i];
After we need to create object outside of our function scope since we return by value and for that move constructor called:
return result;
Then bind object constructed with move constructor in main
scope to const reference:
const MyClass& a = max(arr, 1);
Upvotes: 1
Reputation: 11787
What is the reason that I need
copy constructor
for the typeT
?
T result = array[0];
This is known as a copy initialization and invokes the copy constructor for the type T
. Type T
will require a copy constructor for this line to succeed.
I think that it's must be because that we return by a value, and so we need
copy constructor
forT
type.
return result;
For the most part, your assumption is correct for the return value. However, it isn't necessary for a copy constructor to be defined in this case. To implement move semantics, you can implement a move constructor which will remove the need for the copy constructor, since the local variable result
will be "moved" instead of "copied" from. Move semantics remove the need for unnecessary copies of large objects when returning them from a function, since those large objects will not be accessible after the function returns.
Upvotes: 5