我可以想到填充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,将在数据段中分配内存。如果我使用第二种或第三种方法,是否会在堆栈上分配内存?
答案 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);