C++ 访问元素
示例
访问元素中的元素有两种主要方法 std::vector
基于索引的访问
迭代器
基于索引的访问:
这可以通过下标运算符[]或成员函数来完成at()。
两者均会返回对元素中相应位置的引用std::vector(除非是vector<bool>),以便可以读取和修改该元素(如果向量不是const)。
[]和at()不同之处在于,[]它不能保证同时执行任何边界检查at()。访问元素index < 0或index >= size为时未定义行为的元素[],而at()抛出std::out_of_range异常。
注意:为了清楚起见,以下示例使用C ++ 11样式的初始化,但是运算符可用于所有版本(除非标记为C ++ 11)。
C ++ 11std::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()')以防止未定义的行为。然后计算向量中数字的总和并显示给用户。
C ++ 11该data()方法返回一个指针,该指针指向用来std::vector内部存储其元素的原始内存。在将向量数据传递给期望使用C样式数组的旧代码时,通常使用此方法。
std::vector<int> v{ 1, 2, 3, 4 }; // v包含{1、2、3、4}C ++ 11int* 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}
在C ++ 11之前,data()可以通过调用front()并获取返回值的地址来模拟该方法:
std::vector<int> v(4);int* ptr = &(v.front()); // or &v[0]
之所以可行,是因为假设矢量的内容不会覆盖unary,则始终可以保证矢量将其元素存储在连续的内存位置中operator&。如果是这样,则必须std::addressof在C ++ 11之前的版本中重新实现。它还假定向量不为空。
迭代器:
迭代器在示例“迭代之上std::vector”和文章迭代器中有更详细的说明。简而言之,它们的作用类似于指向向量元素的指针:
C ++ 11std::vector<int> v{ 4, 5, 6 };auto it = v.begin();
int i = *it; // 我4岁
++it;
i = *it; // 我5岁
*it = 6; // v包含{4,6,6}
auto e = v.end(); // e指向v结束后的元素。可以是
// 用于检查迭代器是否到达向量的末尾:
++it;
it == v.end(); // false,它指向位置2处的元素(值6)
++it;
it == v.end(); // 真正
std::vector<T>迭代器实际为 T*s与标准是一致的,但是大多数标准库都不这样做。不这样做会改善错误消息,捕获不可移植的代码,并且可用于在非发行版中通过调试检查来对迭代器进行检测。然后,在发行版本中,围绕基础指针的类被优化了。
您可以持久保存对向量元素的引用或指针,以进行间接访问。这些对元素中元素的引用或指针vector保持稳定,并且访问保持定义,除非您在中的元素之前或之后添加/删除元素vector,或者导致vector容量发生变化。这与使迭代器无效的规则相同。
C ++ 11std::vector<int> v{ 1, 2, 3 };int* p = v.data() + 1; // p指向2
v.insert(v.begin(), 0); // p现在无效,访问* p是未定义的行为。
p = v.data() + 1; // p指向1
v.reserve(10); // p现在无效,访问* p是未定义的行为。
p = v.data() + 1; // p指向1
v.erase(v.begin()); // p现在无效,访问* p是未定义的行为。
以上是 C++ 访问元素 的全部内容, 来源链接: utcz.com/z/340656.html