5

我能想到三种填表的方法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是在主函数之外声明的。根据this answer,内存将分配在数据段中。如果我使用第二种或第三种方法,内存会分配在堆栈上吗?

4

5 回答 5

9

你如何使用这个任务的向量成员?

std::vector<int> v(100);
v.assign(3, 1); // this is what you should do.
于 2011-01-11T19:29:31.660 回答
3

所以,这里有区别,我会让你决定什么最适合你的情况。

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

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

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

除了创建一个额外的临时向量之外,它的作用几乎相同复制 3 个元素。为 v 分配的底层内存大小仍然足以容纳 100 个整数。

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

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

这是缩小向量的唯一方法。

于 2011-01-11T19:39:59.737 回答
2

先回答第二个问题:vector总是会为它包含的对象动态分配内存,所以最终会在堆上。

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

于 2011-01-11T19:29:14.170 回答
1

在之前的文章中没有提到的一个问题对于在这些替代方案中进行选择很重要。即异常安全。具有很强的vector<int>(3, 1).swap(v);异常安全保障。如果以交换的形式实施分配,该表格v = vector<int>(3, 1);也可能提供这种保证。第一种选择并不安全:v.clear(); v.resize(3, 1);

于 2011-01-11T20:09:56.010 回答
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()以说服自己。

于 2011-01-11T19:33:16.410 回答