C++ 访问元素
示例
访问元素中的元素有两种主要方法std::vector
基于索引的访问
迭代器
基于索引的访问:
这可以通过下标运算符[]或成员函数来完成at()。
两者均会返回对元素中相应位置的引用std::vector(除非是vector<bool>),以便可以读取和修改该元素(如果向量不是const)。
[]和at()不同之处在于,[]它不能保证同时执行任何边界检查at()。访问元素index<0或index>=size为时未定义行为的元素[],而at()抛出std::out_of_range异常。
注意:为了清楚起见,以下示例使用C++11样式的初始化,但是运算符可用于所有版本(除非标记为C++11)。
std::vector<int> v{ 1, 2, 3 };
//使用[] int a = v[1]; //一个是2 v[1] = 4; //v现在包含{1,4,3} //使用at() int b = v.at(2); //b是3 v.at(2) = 5; //v现在包含{1,4,5} int c = v.at(3); //引发std::out_of_range异常
由于该at()方法执行边界检查并可能引发异常,因此它比慢[]。这将成为[]首选代码,在该代码中,操作的语义可确保索引处于范围内。在任何情况下,对向量元素的访问都在固定时间内完成。这意味着访问向量的第一个元素的时间(时间)与访问第二个元素,第三个元素等的代价相同。
例如,考虑此循环
for (std::size_t i = 0; i < v.size(); ++i) { v[i] = 1; }
在这里,我们知道index变量i始终处于界限内,因此i对于每次调用都检查界限是否在CPU周期内是浪费的operator[]。
的front()和back()成员函数允许向量的第一和最后一个元素容易参考存取,分别。这些位置是经常使用的,特殊访问器比使用[]以下方法的替代方法更具可读性:
std::vector<int> v{ 4, 5, 6 }; //在C++11之前的版本中,这比较冗长 int a = v.front(); //a为4,v.front()等同于v[0] v.front() = 3; //v现在包含{3,5,6} int b = v.back(); //b为6,v.back()等同于v[v.size()-1] v.back() = 7; //v现在包含{3,5,7}
注意:调用front()或back()在空向量上是未定义的行为。您需要empty()在调用front()或之前使用成员函数(用于检查容器是否为空)检查容器是否为空back()。以下是使用'empty()'测试空向量的简单示例:
int main () { std::vector<int> v; int sum (0); for (int i=1;i<=10;i++) v.push_back(i);//创建并初始化向量 while (!v.empty())//循环直到向量测试为空 { sum += v.back();//保持连续运行 v.pop_back();//弹出将其从向量中删除的元素 } std::cout << "total: " << sum << '\n';//将总数输出给用户 return 0; }
上面的示例创建了一个向量,该向量的序列从1到10。然后弹出向量的元素,直到向量为空(使用'empty()')以防止未定义的行为。然后计算向量中数字的总和并显示给用户。
该data()方法返回一个指针,该指针指向用来std::vector内部存储其元素的原始内存。在将向量数据传递给期望使用C样式数组的旧代码时,通常使用此方法。
std::vector<int> v{ 1, 2, 3, 4 }; //v包含{1、2、3、4} int* p = v.data(); //p指向1 *p = 4; //v现在包含{4,2,3,4} ++p; //p指向2 *p = 3; //v现在包含{4,3,3,4} p[1] = 2; //v现在包含{4,3,2,4} *(p + 2) = 1; //v现在包含{4,3,2,1}