关于填充矢量的不同方式

时间:2011-01-11 19:25:42

标签: c++ stdvector

我可以想到填充std::vector

的三种方法

假设我们有

vector<int> v(100, 0);

然后我想要它(1,1,1)。我们可以这样做:

v.clear();
v.resize(3, 1);

或者

v = vector<int>(3, 1);

我学到了另一种方法:

vector<int>(3, 1).swap(v); 

第一个问题是:它们中的任何一种都是最好的方法吗?

第二个问题:假设v在主函数之外被声明。根据此answer,将在数据段中分配内存。如果我使用第二种或第三种方法,是否会在堆栈上分配内存?

5 个答案:

答案 0 :(得分:9)

你如何使用那里的矢量成员来完成这项任务?

std::vector<int> v(100);
v.assign(3, 1); // this is what you should do.

答案 1 :(得分:3)

所以,这是差异,我会让你决定什么是最适合你的情况。

v.clear();
v.resize(3, 1);

在这种情况下,我们已将矢量标记为已清除。它仍保留它分配的任何东西,以容纳100个元素(可能超过100个元素所需的空间)。然后我们添加了3个值为1的项。所有这些都是增加大小计数器并重置3个值,底层内存仍然是相同的大小。

v = vector<int>(3, 1);

这几乎完全相同,只是创建了一个额外的矢量临时值,而不是存在计数器为0的间歇性位置,然后是具有某些值的3,它简单地复制计数器大小然后执行类似于一个memcpy复制3个元素。为v分配的底层内存大小仍足以容纳100个整数。

vector<int>(3, 1).swap(v); 

这一点有很大不同。在这种情况下,我们创建一个临时向量,其中包含3个元素,这些元素都被初始化为1.理论上它仍然可以为100个元素保留足够的内存,但可能性要少得多。然后我们将这个向量与我们自己交换,让临时被破坏。这具有额外的好处,即清除我们的旧向量分配的任何额外内存,而不是临时的。这种方式的工作方式是两个向量(我们的v和临时)交换的不仅仅是计数器和值,它们还交换缓冲区指针。

这是收缩矢量的唯一方法。

答案 2 :(得分:2)

首先回答第二个问题:vector将始终为其包含的对象动态分配内存,因此它最终会在堆上。

关于哪种重新分配方法更好,我会说你的第一种或第二种方法使你的意图最清晰,这是最重要的属性。

答案 3 :(得分:1)

交换将有效地将向量缩小为3个元素。其他可能不会。

vector<int> v(100);
v.assign(3, 1);
assert(v.size() == 3);
assert(v.capacity() != 3);

v = vector<int>(3, 1);
// Now, v.capacity() is likely not to be 3.

vector<int>(3, 1).swap(v);
assert(v.capacity() == 3);

其他方法不会在内部调整向量。它仍会在内存中占用100 * sizeof(int)字节,即使size()成员返回3.尝试显示v.capacity()以说服自己。

答案 4 :(得分:1)

在以前的帖子中没有提到的一个问题在选择这些替代方案时很重要。即,例外安全。 vector<int>(3, 1).swap(v);具有强大的异常安全保障。如果以交换方式实施分配,表单v = vector<int>(3, 1);也可能提供此类保证。第一种选择是不安全的:v.clear(); v.resize(3, 1);