用C++填充一个乱序数据的向量

3

我希望用vector填充一些数据,这些数据在运行时是已知的,但元素是以(索引、值)对的形式而不是原始顺序出现的。这些索引保证是唯一的(每个从0到n-1的索引恰好出现一次),因此我想按以下方式存储它们:

vector<Foo> myVector;
myVector.reserve(n); //total size of data is known
myVector[i_0] = v_0; //data v_0 goes at index i_0 (not necessarily 0)
...
myVector[i_n_minus_1] = v_n_minus_1;

这看起来大部分情况下都可以正常工作;在代码的末尾,所有的 n 个元素都在向量中安置到了正确的位置。然而,某些向量函数并不完全像预期的那样工作:

...
cout << myVector.size(); //prints 0, not n!

对我来说,像 size() 这样的函数仍然很重要--例如,我可能想检查所有元素是否都成功插入,通过检查 size() == n。我是否初始化了向量错误,如果是,我应该如何处理?


3
这是因为reserve不会调整向量大小。你应该使用vector.resize - Anycorn
Foo 是默认可构造的吗?迄今为止,三个解决方案都假定它是默认可构造的。否则,可能需要存储输入值,然后一次性构造所有 Foo - MSalters
2个回答

5

myVector.reserve(n)告诉向量为n个元素分配足够的存储空间,这样当你往向量中添加新元素时,向量就不必不断地重新分配更多的存储空间。可能需要这样做多次,因为它无法预先知道你将插入多少个元素。换句话说,通过告诉向量实现一些它本来不知道的东西,并使其更加高效。

但是,reserve并没有使向量实际上成为长度为n的向量。向量是空的,实际上类似于myVector[0] = something之类的语句是非法的,因为向量的大小为0:在我的实现中,我会得到一个断言失败,“vector subscript out of range”。这是在Visual C++ 2012上,但我认为gcc也是类似的。

要创建所需长度的向量,只需执行

vector<Foo> myVector(n);

忘记reserve

(如评论所述,您也可以调用resize来设置向量大小,但在您的情况下,将大小作为构造函数参数传递更简单。)


我认为GCC没有进行相同的检查,因为G++并不像VC++那样真正执行“_DEBUG”构建。在这一点上,我认为VC++胜过了G++。 - Mooing Duck
1
@MooingDuck 谢谢。我曾以为gcc会选择SGI/stlport实现。在Windows上,我使用了多年,直到微软最终做出了改变。SGI stl提供了检查功能,但需要手动开启。这里有一个关于在gcc中启用检查的答案。但正如你所说,你必须手动配置makefile或其他工具来拥有单独的DEBUG和RELEASE模式(我记得在90年代我在*nix devmnt上工作时就有这个)。 - TooTone
gcc并不相似。范围检查默认情况下未启用(请参见https://dev59.com/42035IYBdhLWcg3wJcjT#5594728) - TooTone

4

您需要调用myVector.resize(n)来设置(更改)向量的大小。调用reserve实际上并不会调整向量的大小,它只是使您可以稍后重新调整大小而不重新分配内存。在向量末尾写入(就像您在这里做的一样 - 当您写入时,向量大小仍为0)是未定义的行为。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接