使用C ++ 11基于范围的for
?
应该使用什么语法? for (auto elem : container)
,
还是for (auto& elem : container)
或for (const auto& elem : container)
?
还是其他一些?
答案 0 :(得分:11)
使用for (auto elem : container)
或for (auto& elem : container)
或for (const auto& elem : container)
没有正确方法。你只是表达你想要的东西。
让我详细说明一下。我们走一走吧。
for (auto elem : container) ...
这个是语法糖:
for(auto it = container.begin(); it != container.end(); ++it) {
// Observe that this is a copy by value.
auto elem = *it;
}
如果容器中包含复制成本低廉的元素,则可以使用此方法。
for (auto& elem : container) ...
这个是语法糖:
for(auto it = container.begin(); it != container.end(); ++it) {
// Now you're directly modifying the elements
// because elem is an lvalue reference
auto& elem = *it;
}
如果要直接写入容器中的元素,请使用此选项,例如。
for (const auto& elem : container) ...
这个是语法糖:
for(auto it = container.begin(); it != container.end(); ++it) {
// You just want to read stuff, no modification
const auto& elem = *it;
}
正如评论所说,只是为了阅读。就是这样,如果使用得当,一切都是“正确的”。
答案 1 :(得分:7)
正确的方法总是
for(auto&& elem : container)
这将保证保留所有语义。
答案 2 :(得分:1)
虽然range-for循环的最初动机可能是容易迭代容器的元素,但语法足够通用,即使对于非纯粹容器的对象也是如此。
for循环的语法要求是range_expression
支持begin()
和end()
作为任一函数 - 作为其计算类型的成员函数或非成员函数接受类型实例的内容。
作为一个人为的例子,可以使用以下类生成一系列数字并迭代该范围。
struct Range
{
struct Iterator
{
Iterator(int v, int s) : val(v), step(s) {}
int operator*() const
{
return val;
}
Iterator& operator++()
{
val += step;
return *this;
}
bool operator!=(Iterator const& rhs) const
{
return (this->val < rhs.val);
}
int val;
int step;
};
Range(int l, int h, int s=1) : low(l), high(h), step(s) {}
Iterator begin() const
{
return Iterator(low, step);
}
Iterator end() const
{
return Iterator(high, 1);
}
int low, high, step;
};
使用以下main
功能
#include <iostream>
int main()
{
Range r1(1, 10);
for ( auto item : r1 )
{
std::cout << item << " ";
}
std::cout << std::endl;
Range r2(1, 20, 2);
for ( auto item : r2 )
{
std::cout << item << " ";
}
std::cout << std::endl;
Range r3(1, 20, 3);
for ( auto item : r3 )
{
std::cout << item << " ";
}
std::cout << std::endl;
}
将获得以下输出。
1 2 3 4 5 6 7 8 9
1 3 5 7 9 11 13 15 17 19
1 4 7 10 13 16 19