如果我制作这样的矢量:
vector<int>(50000000, 0);
内部会发生什么?它是否构成默认向量然后不断添加值,并根据需要调整大小?注意:编译时不知道50,000,000。
如果我像这样制作矢量会不会有所不同:
gVec = vector<int>();
gVec.reserve(50000000);
// push_back default values
请告诉我构造函数知道在给定两个参数的情况下避免不必要的重新分配。
答案 0 :(得分:3)
如果我像这样制作矢量会不会有所不同:
gVec = vector<int>(); gVec.reserve(50000000); // push_back default values
是的,它确实有所作为使用push_back()
填写默认值可能会降低效率。
要使用与构造函数vector<int>(50000000, 0);
完成相同的操作,请使用std::vector<int>::resize()
:
vector<int> gVec;
gVec.resize(50000000,0);
答案 1 :(得分:3)
通过逐步调试调试器中的两个选项,您将大大增强您从这个问题中学到的东西 - 看看std::vector
源代码的作用是否具有指导性,如果您能够在精神上过滤掉许多最初混淆的内容模板和内存分配抽象。为自己揭开神秘面纱 - STL只是别人的代码,而且我的大部分工作时间都花在了这上面。
std::vector
保证连续存储,因此只为元素分配了一个内存块。 vector
控制结构需要第二次分配,如果它是基于堆的而不是RAII(基于堆栈)。
vector<int>(N, 0);
创建capacity
&gt; = N和size
N的向量,其中N值均设置为0
。
一步一步:
gVec = vector<int>();
创建一个空向量,通常使用名义上的“最佳猜测”capacity
。
gVec.reserve(N);
更新向量的capacity
- 确保向量有至少N个元素的空间。通常,这涉及从“最佳猜测”默认capacity
重新分配,这对于此问题中提出的N值不太可能足够大。
// push_back default values
此处的每次迭代都会将向量的size
增加1,并将向量的新back()
元素设置为0
。在推送的值数超过capacity
(通常为无)之前,向量的N plus whatever pad the vector implementation might have applied
不会更改。
答案 2 :(得分:2)
reserve
仅分配存储空间。不执行初始化。在空vector
上应用它应该导致对所使用的分配器的allocate
成员函数的一次调用。
显示的构造函数分配所需的存储并将每个元素初始化为零:它在语义上等同于reserve
和一行push_back
。
在这两种情况下都没有重新分配。
答案 3 :(得分:2)
我认为理论上构造函数可以通过分配一小块内存并在返回之前扩展几次来开始,至少对于在其复制构造函数中没有副作用的类型而言。这是允许的,因为这样做没有可观察到的副作用,不是因为标准做任何事情直接允许它。
至少在我看来,不值得花费任何时间或精力来担心这种可能性。至少可以说,任何人这样做的机会似乎很遥远。只有“允许”才能真正禁止它。