我现在正在学习C ++,而且我看到很多方法来迭代一个向量。 我想知道,因为我想以正确的方式学习它,现在最正确的迭代方法是什么?
答案 0 :(得分:3)
取决于以下因素:
例如,如果您只想循环std::vector<int> v
元素的某些副本,则可以执行以下操作:
for (int element : v) {
// Use element
}
如果你是AAA人,你可以改为auto element
。
如果你想避免复制,你需要一个const引用:
for (int const &element : v) {
// Use element
}
如果你是AAA人,你可以改为auto const &element
。
如果要修改向量内的值,则需要可修改的引用:
for (int &element : v) {
// Use element
}
再一次,如果您喜欢AAA,那么请改为auto &element
。
如果你需要循环中的迭代器:
for (std::vector<int>::iterator it = std::begin(v); it != std::end(v); ++it) {
// Use it
}
如果你是AAA人:
for (auto it = std::begin(v); it != std::end(v); ++it) {
// Use it
}
请注意,如果循环中的代码不依赖于实际类型(这不是很常见),ANA人员也会使用auto
。
另请注意,您通常可以使用<algorithm>
中的相应算法完全避免循环。查看Sean Parent's talk以获取有关此内容的一些信息。他认为任何包含多行的循环都是不好的,通常可以写得更整齐。
答案 1 :(得分:2)
对于所有情境都没有正确的方法。最简单的是for
循环:
std::vector<SomeClass> v;
for (SomeClass& sc : v)
sc.Method();
但在某些情况下,std::for_each
可能更好,甚至可能更好for(;;)
。
答案 2 :(得分:2)
使用Iterators ...它们是专门为此目的而设计的,适用于所有STL数据结构
http://www.cplusplus.com/reference/vector/vector/begin/
^链接将有助于理解示例
答案 3 :(得分:0)
迭代向量的方式取决于迭代的目的。示例如下。
标准库算法
如果您的目的存在标准库算法,请使用它。当操作可以简单地使用lambda,函数或仿函数表示时,这包括搜索,累积,转换等。它还允许您通过提供适当的迭代器来迭代您选择的范围,即不只是begin
和end
。
示例:计算向量的前20个元素的总和
std::vector<int> v = { /* fill as appropriate */ };
int sum_20 = std::accumulate(std::begin(v), std::begin(v)+20, 0);
示例:将每个元素加倍并存储在另一个向量
中std::vector<int> v = { /* fill as appropriate */ };
std::vector<int> doubled;
doubled.reserve(v.size()); // avoid reallocations
std::transform(std::begin(v), std::end(v),
std::back_inserter(doubled), [](int x){return x*2;})
基于范围的
示例:
std::vector<int> v = { /* fill as appropriate */ };
for (int& x : v)
{
do_something_with(x);
do_another_thing_with(x);
if (some_condition(x))
{
do_something_else();
}
}
这适用于遍历整个容器,其中您想要执行的操作比您想要在一个普通的lambda中表示的更复杂,但不够大(或使用)不止一次)证明自己的功能。
您还可以在一定程度上自定义访问元素的方式。如果元素很大,而您只是阅读它们,则可以指定const foo&
:
for (const MyBigObject& : MyBigContainer) { /* ... */ }
如果您需要修改它们,请删除const:
for (MyBigObject& : MyBigContainer) { /* ... */ }
对于小物件或需要副本的地方,请删除参考:
for (int x : MyVecInt) { /* ... */ }
这允许您为访问指定最合适的常量,并控制您是通过引用还是值访问。类似的事情可以通过提供const或非const迭代器与标准库算法一起完成,并结合适当的参数类型,用于提供给采用可调用实体的算法的任何函数/ functor / lambda。
请注意,基于范围的for只会迭代整个容器,并且没有简单的方法可以同时迭代两个或多个容器。与...相比,这限制了它的适用性。
常规
如果需要同时迭代多个容器,或者需要访问索引或迭代器以及元素本身,那么常规for循环可能是正确的方法。这是最灵活的,允许您自定义迭代的每个方面,但它不会利用任何标准的库优化,并且通常需要更多样板来设置迭代器/索引对,检查您是否'在容器的范围内等等。
示例:
std::vector<int> v1 = {1, 2, 3};
std::vector<int> v2 = {2, 4, 6};
for (std::vector<int>::size_type idx = 0; idx < v1.size(); ++idx)
{
std::cout << v1[idx] * v2[idx] << ", ";
}
std::vector<int> v1 = {1, 2, 3};
auto iter = v1.cbegin();
const auto end = v1.cend() - 1;
for (; iter != end; ++iter)
{
std::cout << *iter + *(iter+1) << "\n";
}
答案 4 :(得分:0)
这取决于你为什么要重复。在许多情况下,你根本不应该迭代;使用标准算法之一。否则,如果要访问仅一个容器的所有元素,则范围for
是最佳解决方案。如果您可能希望尽早中断迭代,那么更喜欢正常的for
,除非(通常情况下)您需要循环后的迭代器,在这种情况下while
可能会更好;在这两种情况下,使用迭代器。最后,如果你并行地迭代几个向量,那么使用一个索引而不是几个迭代器可能更清楚。
总之,这就是为什么你有这么多选择的原因。
答案 5 :(得分:0)
我强烈建议使用range-for循环(自C ++ 11开始)
vector<int> myVector {0, 1, 2, 3, 4};
for (const auto& i : myVector)
cout << i << endl;
预C ++ 11:
std::for_each(myVector.begin(), myVector.end(), myCallable);
C ++ 14不会添加任何有关此场景的内容;可能是C ++ 17,并行循环。
如果您需要使用索引,可以选择“原始”作为
for (auto i = 0; i < myVector.size(); ++i)
这些是最常见的方式。如果您需要更专业的东西,例如排序,移动,查找,请查看<algorithm>
。