C++ 基于范围的for循环
C++11标准对语言引入了许多优秀的、有用的改进。我已经介绍了auto关键字,现在我再来说一下基于范围的for循环。怎样使用?怎样在你自己的类中使用?
1 基于范围的for循环的基本语法
现在,几乎每一个语言都能有一个非常方便的实现for循环的方法。C++也有类似的概念;你可以为你的for循环,添加一个container,他就会自动迭代。我们看下面的例子:
vector<int> vec;
vec.push_back(10);
vec.push_back(20);
for (int i : vec)
{
cout << i;
}
这段代码就是实现了对于vector型变量vec的内容打印,变量i遍历vector中的每一个元素,直到vector的结束。
当然了,在这里,为了迭代更加复杂的数据结构,你可以使用auto关键字。例如,迭代一个map类型数据变量,你可以这样写:
map<string, string> address_book;
for (auto address_entry : address_book)
{
cout << address_entry.first << " < " address_entry.second << " > " << endl;
}
编程人员就不需要担心要迭代类型的拼写了。
2 修改Vector内容
如果你想修改正在遍历的容器里的值,或者你想避免拷贝大量的对象,基本的迭代器就支持,你可以将循环变量作为引用调用。例如,对一个int型vector对象中每一个元素进行自加。
vector<int> vec;
vec.push_back(1);
vec.push_back(2);
for(int& i : vec)
{
// 增加vector对象中元素的值
i++;
}
for (int i : vec)
{
// 显示更新后的数值
cout << i << endl;
}
3 基于范围是什么意思呢?
String,array和所有的STL容器类都能被这种新的基于范围的for循环迭代。但是,如果你将新语法应用到你自定义的数据结构上呢?
为了使一个数据具有可迭代性,他必须与STL迭代具有相似的工作属性。
- (1)具有begin和end方法,即可以作为成员函数也可以作为独立的函数,函数返回数据结构开始和结束的迭代器。
- (2)迭代器必须支持操作符*,!=,++,即可以作为成员函数也可作为独立函数(详细的信息可以参考操作符重载)。
在这里请注意,++操作符必须是前缀的,它被声明为不带参数的operator函数。
就是这样,用这五个函数,你就可以造一个数据结构,能够满足基于范围的for循环。但是begin()和end()方法是非成员函数(begin(container)代替container.begin()),你甚至可以为了适应已经存在的数据结构,不必刻意地支持STL类型的迭代器。你必须做的就是创建你自己的迭代器,它支持*(指针),前缀自加(++)和!=还要定义迭代器的begin和end,就可以了。
因为基于范围的循环是如此漂亮,我猜想那些不支持STL iterator的新容器类,都想添加一个适配器,去允许基于范围的for循环的。下面是一个小程序,创建一个简单的迭代器,然后实现基于范围的for循环。其中,首先创建IntVector类型,大小是100,可以被一个迭代器Iter迭代。代码如下:
// a simple iterator sample.
#include <iostream>
using namespace std;
// forward-declaration to allow use in Iter
class IntVector;
class Iter
{
private:
int _pos;
const IntVector *_p_vec;
public:
Iter(const IntVector* p_vec, int pos) : _pos(pos), _p_vec(p_vec){}
// these three methods form the basis of an iterator for use with a range-based for loop
bool operator!=(const Iter& other) const
{
return _pos != other._pos;
}
// this method must be defined after the definition of IntVector since it needs to use it
int operator*() const;
const Iter& operator++()
{
++_pos;
// although not strictly necessary for a range-based for loop
// following the normal convention of returning a value from
// operator++ is a good idea.
return *this;
}
};
class IntVector
{
private:
int _data[100];
public:
IntVector(){}
int get(int col) const
{
return _data[col];
}
Iter begin() const
{
return Iter(this, 0);
}
Iter end() const
{
return Iter(this, 100);
}
void set(int index, int val)
{
_data[index] = val;
}
};
int Iter::operator*() const
{
return _p_vec->get(_pos);
}
// sample usage of the range-based for loop on IntVector
int main()
{
IntVector v;
for(int i = 0; i < 100; i++)
{
v.set(i,i);
}
for( int i : v)
{
cout << i << endl;
}
}
这段代码需要注意的是,它不允许在for循环中使用引用&,而去实现IntVector元素的修改。这很容易实现,改变get()的返回值为一个引用,但是这样做,会使代码变长,我们这里只是关注基本结构。
4 基于范围的循环增加性能吗?
用GCC4.6版本编译器测试,发现基于范围的for循环并没有比正常的STL迭代器有性能方面的提升,但是似乎跟STL的for_each函数对性能的提升是一样的,for_each函数使用了和迭代器相同的迭代模型。
5 编译器的支持度
不幸的是,基于范围的循环没有被很好滴支持。GCC4.6版本以上。
C++11标准对语言引入了许多优秀的、有用的改进。我已经介绍了auto关键字,现在我再来说一下基于范围的for循环。怎样使用?怎样在你自己的类中使用?1 基于范围的for循环的基本语法现在,几乎每一个语言都能有一个非常方便的实现for循环的方法。C++也有类似的概念;你可以为你的for循环,添加一个container,他就会自动迭代。我们看下面的例子:
vector<int> vec;vec.push_back(10);vec.push_back(20);
for (int i : vec){ cout << i;}12345678这段代码就是实现了对于vector型变量vec的内容打印,变量i遍历vector中的每一个元素,直到vector的结束。当然了,在这里,为了迭代更加复杂的数据结构,你可以使用auto关键字。例如,迭代一个map类型数据变量,你可以这样写:
map<string, string> address_book;for (auto address_entry : address_book){ cout << address_entry.first << " < " address_entry.second << " > " << endl;}12345编程人员就不需要担心要迭代类型的拼写了。
2 修改Vector内容如果你想修改正在遍历的容器里的值,或者你想避免拷贝大量的对象,基本的迭代器就支持,你可以将循环变量作为引用调用。例如,对一个int型vector对象中每一个元素进行自加。
vector<int> vec;vec.push_back(1);vec.push_back(2);
for(int& i : vec){ // 增加vector对象中元素的值 i++; }
for (int i : vec){ // 显示更新后的数值 cout << i << endl;}1234567891011121314153 基于范围是什么意思呢?String,array和所有的STL容器类都能被这种新的基于范围的for循环迭代。但是,如果你将新语法应用到你自定义的数据结构上呢?为了使一个数据具有可迭代性,他必须与STL迭代具有相似的工作属性。
(1)具有begin和end方法,即可以作为成员函数也可以作为独立的函数,函数返回数据结构开始和结束的迭代器。(2)迭代器必须支持操作符*,!=,++,即可以作为成员函数也可作为独立函数(详细的信息可以参考操作符重载)。在这里请注意,++操作符必须是前缀的,它被声明为不带参数的operator函数。
就是这样,用这五个函数,你就可以造一个数据结构,能够满足基于范围的for循环。但是begin()和end()方法是非成员函数(begin(container)代替container.begin()),你甚至可以为了适应已经存在的数据结构,不必刻意地支持STL类型的迭代器。你必须做的就是创建你自己的迭代器,它支持*(指针),前缀自加(++)和!=还要定义迭代器的begin和end,就可以了。
因为基于范围的循环是如此漂亮,我猜想那些不支持STL iterator的新容器类,都想添加一个适配器,去允许基于范围的for循环的。下面是一个小程序,创建一个简单的迭代器,然后实现基于范围的for循环。其中,首先创建IntVector类型,大小是100,可以被一个迭代器Iter迭代。代码如下:
// a simple iterator sample.
#include <iostream>
using namespace std;
// forward-declaration to allow use in Iterclass IntVector;
class Iter{private: int _pos; const IntVector *_p_vec;
public: Iter(const IntVector* p_vec, int pos) : _pos(pos), _p_vec(p_vec){}
// these three methods form the basis of an iterator for use with a range-based for loop bool operator!=(const Iter& other) const { return _pos != other._pos; }
// this method must be defined after the definition of IntVector since it needs to use it int operator*() const; const Iter& operator++() { ++_pos; // although not strictly necessary for a range-based for loop // following the normal convention of returning a value from // operator++ is a good idea. return *this; }};
class IntVector{private: int _data[100];
public: IntVector(){}
int get(int col) const { return _data[col]; }
Iter begin() const { return Iter(this, 0); }
Iter end() const { return Iter(this, 100); }
void set(int index, int val) { _data[index] = val; }};
int Iter::operator*() const{ return _p_vec->get(_pos);}
// sample usage of the range-based for loop on IntVectorint main(){ IntVector v;
for(int i = 0; i < 100; i++) { v.set(i,i); } for( int i : v) { cout << i << endl; }}
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384这段代码需要注意的是,它不允许在for循环中使用引用&,而去实现IntVector元素的修改。这很容易实现,改变get()的返回值为一个引用,但是这样做,会使代码变长,我们这里只是关注基本结构。
4 基于范围的循环增加性能吗?
用GCC4.6版本编译器测试,发现基于范围的for循环并没有比正常的STL迭代器有性能方面的提升,但是似乎跟STL的for_each函数对性能的提升是一样的,for_each函数使用了和迭代器相同的迭代模型。
5 编译器的支持度
不幸的是,基于范围的循环没有被很好滴支持。GCC4.6版本以上————————————————版权声明:本文为CSDN博主「tupelo-shen」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/shenwanjiang111/article/details/59511235
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 【.NET】调用本地 Deepseek 模型
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库