我不熟悉c++语言。我已经开始使用向量,并注意到在我看到的所有通过索引遍历向量的代码中,for循环的第一个参数总是基于向量的值。在Java中,我可以对数组列表做这样的事情:
for(int i=0; i < vector.size(); i++){
vector[i].doSomething();
}
我在c++中看不到这个的原因是什么呢?这是不好的做法吗?
我不熟悉c++语言。我已经开始使用向量,并注意到在我看到的所有通过索引遍历向量的代码中,for循环的第一个参数总是基于向量的值。在Java中,我可以对数组列表做这样的事情:
for(int i=0; i < vector.size(); i++){
vector[i].doSomething();
}
我在c++中看不到这个的原因是什么呢?这是不好的做法吗?
当前回答
如果你使用
std::vector<std::reference_wrapper<std::string>> names{ };
不要忘记,当你在for循环中使用auto时,也要使用get,就像这样:
for (auto element in : names)
{
element.get()//do something
}
其他回答
正确的做法是:
for(std::vector<T>::iterator it = v.begin(); it != v.end(); ++it) {
it->doSomething();
}
其中T是向量中类的类型。例如,如果类是CActivity,只需写CActivity而不是T。
这种类型的方法将适用于每个STL(不仅仅是向量,这是更好的一点)。
如果你仍然想使用索引,方法是:
for(std::vector<T>::size_type i = 0; i != v.size(); i++) {
v[i].doSomething();
}
令我惊讶的是,没有人提到遍历具有整数索引的数组会很容易通过下标具有错误索引的数组来编写错误代码。例如,如果使用i和j作为下标嵌套循环,则可能错误地将数组下标为j而不是i,从而在程序中引入错误。
相比之下,这里列出的其他形式,即基于范围的for循环和迭代器,更不容易出错。该语言的语义和编译器的类型检查机制将防止您意外地使用错误的索引访问数组。
这是一个更简单的方法来迭代和打印值在向量。
for(int x: A) // for integer x in vector A
cout<< x <<" ";
在vector上迭代并打印其值的正确方法如下:
#include<vector>
// declare the vector of type int
vector<int> v;
// insert elements in the vector
for (unsigned int i = 0; i < 5; ++i){
v.push_back(i);
}
// print those elements
for (auto it = v.begin(); it != v.end(); ++it){
std::cout << *it << std::endl;
}
但至少在目前的情况下,使用基于范围的for循环会更好: 对于(auto x: v) std::cout << x << "\n"; (你也可以在auto后面加上&,使x成为对元素的引用,而不是它们的副本。它与上面的基于迭代器的方法非常相似,但更易于读写。)
遍历vector最简洁的方法是通过迭代器:
for (auto it = begin (vector); it != end (vector); ++it) {
it->doSomething ();
}
或(相当于上述)
for (auto & element : vector) {
element.doSomething ();
}
在c++ 0x之前,必须将auto替换为迭代器类型,并使用成员函数而不是全局函数begin和end。
This probably is what you have seen. Compared to the approach you mention, the advantage is that you do not heavily depend on the type of vector. If you change vector to a different "collection-type" class, your code will probably still work. You can, however, do something similar in Java as well. There is not much difference conceptually; C++, however, uses templates to implement this (as compared to generics in Java); hence the approach will work for all types for which begin and end functions are defined, even for non-class types such as static arrays. See here: How does the range-based for work for plain arrays?