我正在为我的vector
成员变量预先分配一些内存。下面的代码是最小部分
class A {
vector<string> t_Names;
public:
A () : t_Names(1000) {}
};
现在在某个时间点,如果t_Names.size()
等于1000
。我打算将大小增加100
。然后,如果它达到1100
,则再增加100
,依此类推。
我的问题是,在vector::resize()
和vector::reserve()
之间选择什么。在这种情况下还有更好的选择吗?
修改:我对t_Names
进行了精确估算。我估计它在700
到800
附近。但是,在某些(很少)的情况下,它可能会增长超过1000
。
答案 0 :(得分:230)
这两个功能完全不同!
resize()
方法(并且向构造函数传递参数等价于此)将向向量插入或删除适当数量的元素以使其具有给定大小(它具有可选的第二个参数来指定它们的值)。它将影响size()
,迭代将覆盖所有这些元素,push_back将在它们之后插入,您可以使用operator[]
直接访问它们。
reserve()
方法仅分配内存,但保留未初始化状态。它仅影响capacity()
,但size()
将保持不变。对象没有值,因为向量中没有添加任何内容。如果然后插入元素,则不会重新分配,因为它是事先完成的,但这是唯一的效果。
所以这取决于你想要什么。如果您想要一个包含1000个默认项的数组,请使用resize()
。如果您想要一个阵列,您希望插入1000个项目,并希望避免一些分配,请使用reserve()
。
编辑: Blastfurnace的评论让我再次阅读了这个问题并意识到,在您的情况下,正确的答案是不要手动预分配。只需根据需要在元素末端插入元素即可。向量将根据需要自动重新分配,并且将比提到的手动方式有效地更多。 reserve()
有意义的唯一情况是,您需要提前轻松获得所需总大小的合理精确估计值。
EDIT2 :广告问题编辑:如果您有初步估算值,那么估算值为reserve()
。如果事实证明还不够,那就让矢量做就好了。
答案 1 :(得分:26)
resize()
不仅会分配内存,还会创建与所需大小一样多的实例,并将其作为参数传递给resize()
。但是reserve()
只分配内存,它不会创建实例。也就是说,
std::vector<int> v1;
v1.resize(1000); //allocation + instance creation
cout <<(v1.size() == 1000)<< endl; //prints 1
cout <<(v1.capacity()==1000)<< endl; //prints 1
std::vector<int> v2;
v2.reserve(1000); //only allocation
cout <<(v2.size() == 1000)<< endl; //prints 0
cout <<(v2.capacity()==1000)<< endl; //prints 1
输出(online demo):
1
1
0
1
如果您不想要默认创建的对象,那么resize()
可能不合适。它也会很慢。此外,如果您push_back()
新元素,向量的size()
将通过分配新内存进一步增加(这也意味着将现有元素移动到新分配的内存中)空间)。如果您在开始时使用了reserve()
以确保已经分配了足够的内存,那么当您向size()
发送<{1}}时,向量的push_back()
会增加,但是它不会分配再次使用新内存,直到它为你保留的空间用完。
答案 2 :(得分:2)
保留。另外,在调整大小时,您可能更愿意在逻辑上区分和跟踪其计数与其使用计数。所以界面中存在行为差异 - 向量将在保留时表示相同数量的元素,并且在场景中调整大小时将为100个元素。
在这种情况下还有更好的选择吗?
在对抗默认行为时,完全取决于您的目标。有些人会喜欢定制的分配器 - 但我们真的需要更好地了解你试图在程序中解决的问题,以便为你提供良好的建议。
fwiw,许多矢量实现只会在分配的元素数量必须增长时加倍 - 您是尝试最小化峰值分配大小还是尝试为某些无锁程序或其他东西保留足够的空间?
答案 3 :(得分:1)