即使@JamesMcNellis 的回答是有效的,我还是想解释一下关于错误处理的一些事情,以及还有另一种方法可以做你想做的事情。
您有四种方法可以访问向量中的特定项目:
- 使用
[] 运算符
- 使用成员函数
at(...)
- 结合使用迭代器和给定的偏移量
- 使用标准 C++ 库的
algorithm 标头中的 std::for_each。这是我可以推荐的另一种方式(它在内部使用迭代器)。您可以阅读更多相关信息,例如 here。
在以下示例中,我将使用以下向量作为实验鼠并解释前三种方法:
static const int arr[] = {1, 2, 3, 4};
std::vector<int> v(arr, arr+sizeof(arr)/sizeof(arr[0]));
这将创建一个向量,如下所示:
1 2 3 4
首先让我们看看[]的做事方式。它的工作方式与您在使用普通数组时所期望的方式几乎相同。您提供一个索引,然后可能访问您想要的项目。我说可能是因为[] 运算符不检查向量是否实际上有那么多项目。这会导致静默无效内存访问。示例:
v[10] = 9;
这可能会也可能不会导致即时崩溃。最坏的情况当然是如果它没有,并且您实际上得到了似乎是有效的值。与数组类似,这可能会导致浪费时间来尝试查找原因,例如 1000 行代码稍后您会得到 100 而不是 234 的值,这在某种程度上与您检索项目的那个位置有关来自你的矢量。
更好的方法是使用at(...)。这将自动检查out of bounds 的行为并中断抛出std::out_of_range。所以在我们有的情况下
v.at(10) = 9;
我们会得到:
在抛出 'std::out_of_range' 的实例后调用终止
what(): vector::_M_range_check: __n (即 10) >= this->size()
(即4)
第三种方式类似于[] 运算符,因为您可以把事情搞砸。向量就像数组一样,是一系列包含相同类型数据的连续内存块。这意味着您可以通过将起始地址分配给迭代器来使用起始地址,然后只需向该迭代器添加偏移量。偏移量仅代表您要遍历的第一项之后的项目数:
std::vector<int>::iterator it = v.begin(); // First element of your vector
*(it+0) = 9; // offest = 0 basically means accessing v.begin()
// Now we have 9 2 3 4 instead of 1 2 3 4
*(it+1) = -1; // offset = 1 means first item of v plus an additional one
// Now we have 9 -1 3 4 instead of 9 2 3 4
// ...
如您所见,我们也可以这样做
*(it+10) = 9;
这又是一次无效的内存访问。这与使用at(0 + offset) 基本相同,但没有越界错误检查。
我建议尽可能使用at(...),不仅因为它与迭代器访问相比更具可读性,而且因为我在上面提到的带有偏移组合的迭代器和[] 运算符都对无效索引进行了错误检查.