I have the following code:
#include <iostream>
using std::cin; using std::cout; using std::endl;
#include <vector>
using std::vector;
class Quote {
public:
Quote() = default;
Quote(const std::string &book, double sales_price):
bookNo(book), price(sales_price) { }
// Quote(const Quote&) = default; // memberwise copy
Quote(const Quote &orig): bookNo(orig.bookNo), price(orig.price) {
cout << orig.isbn() << endl;
cout << "called Quote(const Quote &)" << endl;
}
Quote& operator=(const Quote&) = default; // copy assign
std::string isbn() const { return bookNo; }
virtual double net_price(std::size_t n) const
{ cout << "Quote::net_price\n"; return n * price; }
virtual void debug() const { cout << bookNo << ' ' << price << endl; }
virtual ~Quote() = default;
private:
std::string bookNo; // ISBN number of this item
protected:
double price = 0.0; // normal, undiscouted price
};
int main(int argc, char *argv[]) {
vector<Quote> basket;
basket.push_back(Quote("0-201-82470-1", 50));
basket.push_back(Quote("0-201-82XXXXX", 30));
cout << "\ntraverse bakset" << endl;
for (const auto &v : basket)
v.debug();
}
After I compile the above code and run, the result is:
0-201-82470-1
called Quote(const Quote &)
0-201-82XXXXX
called Quote(const Quote &)
0-201-82470-1
called Quote(const Quote &)
traverse bakset
0-201-82470-1 50
0-201-82XXXXX 30
According to when copy constructor is called, it will be called twice because I just have pushed two elements when I push_back()
to a vector. But why it is called three times displayed in the above result.
However, according to the for-loop in main
, the element of the vector is right.
Why the copy constructor is called one more time when pushed to a vector? And is there anything wrong with my defined copy constructor?
As per C++ language open standard draft n3690.pdf regarding vector capacity. Please see the bold italicized statement.
Also from Scott Meyers "Effective C++ Digital Collection: 140 Ways to Improve Your Programming", under item 14 Item 14.
As suggested by "songyuanyao" one should reserve the size(if it is known in advance) to avoid frequent reallocation.
When the push_back is called at the 2nd time, reallocation happened. (More precisely it happens when the new
size()
is greater thancapacity()
.) Then the old underlying storage of thevector
will be destroyed and the new one will be allocated, and elements need to be copied to the new storage, which cause the copy constructor to be called.You can use reserve to avoid reallocation. e.g.