C++11的for循环,以及范围Range类的简单实现_C 语言

C++11支持range-based for循环。这是一个很方便的特性,能省挺多代码。以下代码就能很方便的遍历vector中的元素,并打印出来:

std::vector<int> int_vec;

int_vec.push_back(1);

int_vec.push_back(2);

//如果要修改int_vec中的元素,将变量x声明为 int& 即可

for (int x: int_vec)

{

 std::cout << x << endl;

}

可以遍历的对象包括:

•数组。(不包括指针)
•定义了begin()和end()方法,且返回该方法返回迭代器的类对象。(STL 中所有容器都可以)

(对于动态生成的数组的遍历,用下面介绍的Range类也能省不少代码)

参考 http://en.cppreference.com/w/cpp/language/range-for 可知,

语句 for ( range_declaration : range_expression) loop_statement

与以下语句作用等价:

{ 

 auto && __range = range_expression ; 

 for (auto __begin = begin_expr, 

   __end = end_expr;

   __begin != __end; ++__begin) {

  range_declaration = *__begin; 

 loop_statement

 } 

}

对于可遍历的类对象,__begin和__end分别由类的begin()和end()方法产生。且由于__range变量是右值引用,如果range_expression的结果是右值,其将会在循环结束后析构。

--------------------------------------------------------------------------------

这样,C++11终于支持了这种现代编程语言都支持的遍历方式了。但是,无论是语法还是标准库都不支持对具体数字的遍历,比如python中的 for i in xrange(1,5)语句中,x将连续取[1,4]中的值。(Boost库有irange类可以满足这个需求,但是下面会讨论下我的实现)

最直接的方法,就是写一个函数,返回一个vector<int>对象,其元素为从begin到end的值。但这样每次循环时都得构造一个这样的对象,略慢。

从标准来看,如果一个类要支持这样遍历,至少得有begin()和end()方法。在for循环的初始化部分,调用了这两个方法之后,就没这个类啥事了——都是迭代器的事。所以很自然,从迭代器上下手。这个迭代器必须支持三种操作:!=,前缀++,解引用
。有没发现,如果这个“迭代器”是个int数值的话,上面循环中的__begin!=__end;++__begin语句就是一个非常自然的实现。现在的目标很简单了:这个“迭代器”不遍历容器中的每个元素,而就是一个简单的int数值的封装。对其解引用将返回这个数

,而比较和自加操作均对这个数进行操作。

--------------------------------------------------------------------------------

有想法之后,实现起来就很容易了。首先定义一个仿迭代器 FakeIter ,其对一个数值进行封装,并重载必须的操作符。

class FakeIter

{

 typedef long _VType; //数值的类型为long。当然了,也可以写个模板出来

public:

 explicit FakeIter(_VType val)

  :value_(val){}

 bool operator != (const FakeIter& other) const

 {

  return (this->GetValue()) != (other.GetValue());

 }

 _VType operator* () const

 {

  return GetValue();

 }

 const FakeIter& operator++ ()

 {

  ++value_;

  return *this;

 }

private:

 _VType GetValue() const

 {

  return value_;

 }

 _VType value_;

};

至于“容器”类的实现,就更简单了:实现begin()和end()方法,并返回上面的FakeIter就好了。类中的方法加了一些cout语句,可以更清楚的了解循环执行时具体方法的调用过程,实际用时可以删掉。


class Range

{

 typedef long _VType; //同样,也可以弄个模板出来,但是就不方便用了

public:

 Range (_VType begin_v, _VType end_v)

  :begin_value_(begin_v), end_value_(end_v)

 {

  cout<<"Range::Range()"<<endl;

 }

 ~Range()

 {

  cout<<"Range::~Range()"<<endl;

 }

 FakeIter begin () const

 {

  cout<<"Range::begin()"<<endl;

  return FakeIter(begin_value_);

 }

 FakeIter end () const

 {

  cout<<"Range::end()"<<endl;

  return FakeIter(end_value_ );

 }

private:

 _VType begin_value_;

 _VType end_value_;

}; 

好了,试试看这货有没用:

for (auto x: Range(1,5))

{

 std::cout<<x<<endl;

}

std::cout<<"Loop end"<<endl;

在vs2012及clang下输出如下:

Range::Range()
Range::begin()
Range::end()
1
2
3
4
Range::~Range()
Loop end

嗯,如果把那些影响视线的输出语句的注释掉的话貌似能用了。现在要遍历一个new生成的数组的话,只需用这东西Range个下标,世界就清静了。

但是,步长呢!好吧,貌似我暂时还没这方面的需求。不过实现起来也很简单:修改FakeIter类就可以了,可以增加一个表示步长的成员,然后再修改自加操作。更进一步,也可以加一个生成器方法,就能变成一个更通用的生成器了。配合C++11 lambda操作符,用起来也挺方便。

以上就是小编为大家带来的C++11的for循环,以及范围Range类的简单实现全部内容了,希望大家多多支持~

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索python
, c++11
, for循环
range
random.range取值范围、go range 循环、r语言range函数、range tree范围树、vba range 动态范围,以便于您获取更多的相关知识。

时间: 2024-09-20 13:53:24

C++11的for循环,以及范围Range类的简单实现_C 语言的相关文章

C语言循环结构与时间函数用法实例教程_C 语言

本文实例展示了C语言循环结构与时间函数用法,对于C语言的学习来说是非常不错的参考借鉴材料.分享给大家供大家参考之用.具体如下: 完整实例代码如下: /********************************************** ** <Beginning C 4th Edition> Notes codes ** Created by Goopand ** Compiler: gcc 4.7.0 *****************************************

结合C++11新特性来学习C++中lambda表达式的用法_C 语言

在 C++ 11 中,lambda 表达式(通常称为 "lambda")是一种在被调用的位置或作为参数传递给函数的位置定义匿名函数对象的简便方法. Lambda 通常用于封装传递给算法或异步方法的少量代码行. 本文定义了 lambda 是什么,将 lambda 与其他编程技术进行比较,描述其优点,并提供一个基本示例.Lambda 表达式的各部分ISO C++ 标准展示了作为第三个参数传递给 std::sort() 函数的简单 lambda: #include <algorithm

解析C++中的for循环以及基于范围的for语句使用_C 语言

for循环语句 重复执行语句,直到条件变为 false. 语法 for ( init-expression ; cond-expression ; loop-expression ) statement; 备注 使用 for 语句可构建必须执行指定次数的循环. for 语句包括三个可选部分,如下表所示. for 循环元素 下面的示例将显示使用 for 语句的不同方法. #include <iostream> using namespace std; int main() { // The co

C语言中对于循环结构优化的一些入门级方法简介_C 语言

一.代码移动 将在循环里面多次计算,但是结果不会改变的计算,移到循环外面去. 例子: 优化前: void lower1(char *s){ int i; for(i=0;i<strlen(s);++i) if(s[i]>='A'&&s[i]<='Z') s[i]-=('A'-'a'); } 优化后: void lower2(char *s){ int i; int len=strlen(s); for(int i=0;i<len;++i) if(s[i]>='

C++11的for循环,以及范围Range类的实现

C++11支持range-based for循环.这是一个很方便的特性,能省挺多代码.以下代码就能很方便的遍历vector中的元素,并打印出来: 1 2 3 4 5 6 7 8 std::vector<int> int_vec; int_vec.push_back(1); int_vec.push_back(2); //如果要修改int_vec中的元素,将变量x声明为 int& 即可 for (int x: int_vec) {     std::cout << x <

用金山wps制作循环播放的胶片效果的简单方法

  在今天的金山wps使用教程中,我们将为大家分享的使用技巧是:制作从左往循环播放的胶片效果.不少网友看到这个题目,都会担心这个操作不要太复杂哦!其实,制作的方法非常简单.感兴趣的网友可以按照下面的步骤来一步一步进行,轻松就可以实现了.下面,来看一下金山wps制作从左往循环播放的胶片效果的简单方法! 金山wps 1.首先是胶卷的制作,新建空白幻灯片,画一个矩形,设为黑色,如下图. 金山wps 2.然后画很小的一个矩形,设为白色,放在黑色矩形上. 3.复制粘贴白色矩形,可以使用组合来复制,这样快些

Groovy探索 自定义Range 二 自定义Range类与Decorate模式

Decorate模式相信大家都比较熟悉了,是一个"BangOfFour"中最常用的模式之一,实现起来也相当的简单.如果有人不熟悉的话,可以看看<Groovy探索之Decorate模式>,那里面有一个本篇要沿用的例子. 这个例子就是咖啡馆里买咖啡的经典例子,咖啡有原味咖啡,还有根据顾客口味不同进行各种添加,比如加冰.加奶和加糖等等.顾客可以选择不加.加一样或加多样,各种加法的咖啡所买的价格也不一样. 这个例子是Decorate模式实现的最经典的例子.我们在这里希望使用自定义R

Groovy探索 自定义Range 二 自定义Range类与Decorate模式(下)

顾客可以需要任何种类的咖啡,我们可以根据Range的范围来调节.你可能会说,且慢,如果我只需要咖啡加奶,怎么办? 这就要麻烦一点: def c = new Coffee() def m = new Milk() m.types = ['Coffee','Milk'] (c..m).each{ println it.description() } 麻烦在于我们不能使用"Base"类默认的"types"的值了,需要自定义"types"的值,如: m.

Groovy探索 自定义Range 一 一个简单的自定义Range类

这将是一个系列的文字,用来扩展我们对于自定义Range类的使用思路.也许我们在Groovy语言的编码不知不觉的使用到了Range类,甚至没有觉察到它的存在:或者我们在Groovy语言的编码过程中,常常惊叹于使用Range类的方便,但仅仅是惊叹而已,我们没有付之行动:或者我们想在实际编码中使用自定义的Range类,但却找不到使用它的适当地方.等等,所有这些,希望在读完我们的这个系列后,我们能够将被动的使用Range类,转化为主动的使用我们自定义的Range类. Groovy语言引入的一个重要概念就