我刚开始学习c ++。 我被教会如何编写一个简单的for循环
例如
for (int i = 0; i < vector.size(); i++) {
//do stuff
}
但现在经常会看到人们在 for for循环中使用 auto 这个词。
假设我有一个包含一些数据的向量,这些数据将被带到地图
e.g
以c ++ 11方式
vector<char> vec;
map<char, int> myMap;
vec.push_back('a');
vec.push_back('b');
vec.push_back('b');
vec.push_back('c');
// Loop through the vector
for (auto x : vec) {
++myMap[x];
}
for (auto x : myMap) {
}
相当于
vector<char> vec;
map<char, int> myMap;
vec.push_back('a');
vec.push_back('b');
vec.push_back('b');
vec.push_back('c');
for (int x = 0; x < v.size(); x++) {
++myMap[v[x]];
}
for (int x = 0; x < myMap.size() x++) {
//print content in map
}
答案 0 :(得分:3)
它的效果相当,而不是效率。以下是标准定义的确切翻译:
for (auto element : container) {
//Stuff
}
被转换为这个基于迭代器的循环:
auto&& __range = container;
for (auto __itr = std::begin(container), __end = std::end(container);
__itr != __end; ++__itr) {
element = *__itr;
//Stuff
}
特别是,这是不同的,因为它只评估结束一次(而不是多次调用v.size()
)并且它使用迭代器而不是索引。它还提供了一个更清晰的界面:
很少有其他事情:
1)auto
是一个单独的语言功能。您无需使用auto
来使用基于范围的for循环,例如:
for (int i : { 1, 2, 3, 4, 5}) {
cout << i << endl;
}
打印数字1-5是完全合法的方式。
2)不使用push_back来填充示例向量,而是使用'universal initialization`:
vector<char> vec { 'a', 'b', 'c', 'd' };
3)当使用基于范围的for循环与非基本类型时,更喜欢使用auto&
或const auto&
作为范围声明类型。例如
vector<string> v { "Hello", "world" };
for (const auto& elt : v) {
cout << elt << endl;
}
我们这样做是因为复制基元以外的东西通常很昂贵,默认情况下会复制副本。这里我们使用别名,为我们保存字符串副本,从而节省分配的性能成本。
技术性:我给出的翻译有点不准确,因为它没有以与标准相同的方式处理所有情况(它更喜欢成员函数begin / end和数组得到特殊处理)。我简化了它以便于理解。有关详细信息,请参阅上面的来源。
答案 1 :(得分:1)
您无法取消引用int
变量。您的旧样式示例需要稍微更新:
for (int x= 0 ; ( x < v.size() ) ; x ++ ) {
++ myMap[ v[x] ] ;
}
但在旧式C ++中没有人真正这样做过,他们使用了迭代器:
for ( vector<int>::iterator itptr= v.begin() ; ( itptr != v.end() ) ; ++ itptr ) {
++ myMap[ * itptr ] ;
}
由于auto
:
for ( auto itptr= v.begin() ; ( itptr != v.end() ) ; ++ itptr ) {
++ myMap[ * itptr ] ;
}
但正如您所见,新的for
形式是最简单的:
// Loop through the vector
for (auto x : vec) {
++myMap[x];
}
但请注意我没有取消引用x
,x
就是角色。
答案 2 :(得分:0)
是,它们是等效的。
除了这两种情况之外,不都应该尝试延迟x
,因为在这两种情况下,这都是语法错误。