c++像python一样用range

c++11之后有了 range for 语法,那么那么对于数字的 for,可不可以也用 range for 来写呢。这就要理解 c++11 的 range for 具体是怎么工作的。实际上,c++的 range for 语句,在编译时会被展开,比如这句话

for(auto &p : obj)

实际上会被展开为:

for(auto it=obj.begin(); it!=obj.end(); ++it)

而 range for 中得到的 p 实际上是的 it 的解引用,也就是 p=*it。

从上面可以看到,对于一个obj,其可以使用 range for 的条件是,obj 有至少有两个函数,obj.begin() 和 obj.end()。这两个函数返回相同的类型,这个返回类型我们称为 obj 的迭代器。除了 obj 满足有这两个函数之外,还要求 obj 的迭代器满足下列三个条件

  • 有前置++算符,(展开中的 ++it 要用)
  • 有不等于判断算符,(终止条件是用不等于算符判断的)
  • 有解应用算符,因为 range for 得到的是迭代器的解引用

了解了以上几点,我们就可以写一个自己的 Range 类,使其可以实现整数的 range。

先实现 Range 的迭代器:

class Range_iterator{
public:
    Range_iterator(std::size_t c) : count(c) {}
    ~Range_iterator() = default;

    Range_iterator &operator++() {++count; return *this;}
    bool operator!=(const Range_iterator &ri) {return count != ri.count;}
    std::size_t &operator*() {return count;} 
private:
    std::size_t count;
};

其中特别注意的一点是,解引用算符返回的必须是引用,因为解引用通常都是左值。

接下来就是 Range 了:

class Range{
public:
    Range(std::size_t b, std::size_t e) : Begin(b),End(e) {if(b > e) Begin = End;}
    Range(std::size_t e) : Range(0, e) {}
    ~Range() = default;
    
    Range_iterator begin(){return Range_iterator(Begin);}
    Range_iterator end(){return Range_iterator(End);}
private:
    std::size_t Begin;
    std::size_t End;
};

意外的很简单,我们必须让 Range 记住开始和结尾,迭代过程的自加则交给 Range 的迭代器。

我这里使用 size_t 而不是 int,是因为一般而言,使用 range 还是为了索引,而 c++ 不同于python,是没有负数索引的,而且标准库的 size 一般都是使用等价于 size_t 的类型来表示。

下面测试一下怎么用:

using range = Range;

int main(){
    for(auto &i : range(20)) std::cout << i << ' ';
    std::cout << '\n';
    std::string s = "Hello World!";
    for(auto &i : range(10)) std::cout << s[i] << ' ';
}

这个代码的运行结果是:

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
H e l l o   W o r l 

是不是瞬间感觉清爽了很多。当然这个用法还是其次,这个问题对于理解 c++ 的 range for 还是很有帮助的,我觉得这个代码应该是可以实现 range for 的自定义类型中最简单的了。

源代码下载:https://github.com/0382/cpp_range

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值