Reputation: 1498
I tested the following code:
#include <iostream>
#include <vector>
class foo {
public:
int m_data;
foo(int data) : m_data(data) {
std::cout << "parameterised constructor" << std::endl;
}
foo(const foo &other) : m_data(other.m_data) {
std::cout << "copy constructor" << std::endl;
}
};
main (int argc, char *argv[]) {
std::vector<foo> a(3, foo(3));
std::vector<foo> b(4, foo(4));
//std::vector<foo> b(3, foo(4));
std::cout << "a = b" << std::endl;
a = b;
return 0;
}
I get
parameterised constructor
copy constructor
copy constructor
copy constructor
parameterised constructor
copy constructor
copy constructor
copy constructor
copy constructor
a = b
copy constructor
copy constructor
copy constructor
copy constructor
However, if I replace std::vector<foo> b(4, foo(4));
by std::vector<foo> b(3, foo(4));
the copy constructor is not called by a = b
and the output is
parameterised constructor
copy constructor
copy constructor
copy constructor
parameterised constructor
copy constructor
copy constructor
copy constructor
a = b
Why is in this case the copy constructor not called?
I'm using g++ (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1
Upvotes: 7
Views: 427
Reputation: 15175
It is using the assignment operator.
#include <iostream>
#include <vector>
class foo {
public:
int m_data;
foo(int data) : m_data(data) {
std::cout << "parameterised constructor " << m_data << std::endl;
}
foo(const foo &other) : m_data(other.m_data) {
std::cout << "copy constructor " << m_data << " " << other.m_data << std::endl;
}
foo& operator= (const foo& other){
std::cout << "assignment operator " << m_data << " " << other.m_data << std::endl;
}
};
main (int argc, char *argv[]) {
std::vector<foo> a(3, foo(3));
//std::vector<foo> b(4, foo(4));
std::vector<foo> b(3, foo(4));
std::cout << "a = b" << std::endl;
a = b;
for(std::vector<foo>::const_iterator it = a.begin(); it != a.end(); ++it){
std::cout << "a " << it->m_data << std::endl;
}
for(std::vector<foo>::const_iterator it = b.begin(); it != b.end(); ++it){
std::cout << "b " << it->m_data << std::endl;
}
return 0;
}
parameterised constructor 3
copy constructor 3 3
copy constructor 3 3
copy constructor 3 3
parameterised constructor 4
copy constructor 4 4
copy constructor 4 4
copy constructor 4 4
a = b
assignment operator 3 4
assignment operator 3 4
assignment operator 3 4
a 3
a 3
a 3
b 4
b 4
b 4
See Olis answer for why.
Upvotes: 3
Reputation: 272487
In the first case, a
needs to grow when you assign to it, which means that all its elements must be reallocated (and therefore destructed and constructed).
In the second case, a
does not need to grow, hence the assignment operator is used.
See http://ideone.com/atPt9; adding an overloaded copy assignment operator that prints a message, we get the following for the second example:
parameterised constructor
copy constructor
copy constructor
copy constructor
parameterised constructor
copy constructor
copy constructor
copy constructor
a = b
copy assignment
copy assignment
copy assignment
Upvotes: 12