为什么vector hold类会在push_back()时再次调用copy构造函数?

时间:2017-09-04 02:40:15

标签: c++ vector copy-constructor push-back

我有以下代码:

#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();
}

编译完上面的代码并运行后,结果为:

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

根据调用复制构造函数的时间,它将被调用两次,因为我只是在向push_back()推送了两个元素到向量时。但是为什么在上面的结果中显示三次 但是,根据main中的for循环,向量的元素是正确的。

为什么在推送到向量时再次调用复制构造函数?我定义的拷贝构造函数有什么问题吗?

2 个答案:

答案 0 :(得分:3)

第二次调用push_back时,重新分配。 (更确切地说,当新的@ResponseBody public ResponseEntity somthing() { HttpHeaders headers = new HttpHeaders(); headers.add("Content-Type", "application/json; charset=utf-8"); return new ResponseEntity<>(new Gson().toJson("hello this is my message"), headers, HttpStatus.NOT_FOUND); } 大于size()时会发生这种情况。)然后,capacity()的旧底层存储将被销毁,新的存储将被分配,元素需要被复制到新存储器,这将导致调用复制构造函数。

您可以使用reserve来避免重新分配。 e.g。

vector

答案 1 :(得分:0)

根据C++ language open standard draft n3690.pdf 关于矢量容量。请参阅粗体斜体声明。

  

23.3.7.3载体容量[vector.capacity]   size_type capacity()const noexcept;   1返回:向量可以容纳的元素总数,无需重新分配。   void reserve(size_type n);   2要求:T应为MoveInsertable到* this。   3效果:一种指令,通知向量计划的大小变化,以便它可以管理存储   相应的分配。在reserve()之后,capacity()大于或等于reserve的参数if   重新分配发生;并且等于capacity()的先前值。 “ 重新分配   此时,当且仅当当前容量小于reserve()的参数 “。如果异常   除非由非CopyInsertable类型的move构造函数抛出,否则没有效果

同样来自Scott Meyers的“有效的C ++数字馆藏:改善编程的140种方法”,项目14 第14项。

  

使用reserve来避免不必要的重新分配。   关于STL容器最奇妙的事情之一就是它们会自动增长以容纳您放入的数据,只要您不超过其最大尺寸即可。 (要发现这个最大值,只需调用恰当命名的max_size成员函数。)对于向量和字符串,只要需要更多空间,就可以通过执行realloc的道德等效来处理增长。这种类似realloc的操作有四个部分:   1.分配一个新的内存块,它是容器当前容量的一部分。   在大多数实现中,矢量和字符串容量每次增长1.5到2倍

根据“ songyuanyao ”的建议,应保留大小(如果事先知道),以避免频繁重新分配。

相关问题