IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

在C++中实现foreach循环,比for_each更简洁!

Vimer 2010-10-25 23:44:57 累计浏览 9,500 次
本机暂存

python,c#,java里面都有类似于foreach的结构,stl里面虽然有for_each这个函数,但是感觉使用还是太繁琐了一些,所以就自己实现了一个。 先来看看stl里面的for_each函数,官方文档上的原型如下:

1
Function for_each (InputIterator first, InputIterator last, Function f);

示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// for_each example
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
 
void myfunction (int i) {
  cout << " " << i;
}
 
struct myclass {
  void operator() (int i) {cout << " " << i;}
} myobject;
 
int main () {
  vector<int> myvector;
  myvector.push_back(10);
  myvector.push_back(20);
  myvector.push_back(30);
 
  cout << "myvector contains:";
  for_each (myvector.begin(), myvector.end(), myfunction);
 
  // or:
  cout << "\nmyvector contains:";
  for_each (myvector.begin(), myvector.end(), myobject);
 
  cout << endl;
 
  return 0;
}

不只函数原型有点不习惯,而且还要再写一个函数,比起python的实现方式,的确有点繁琐了:

1
2
for d in l:
    print d

我们来自己实现一个,方法肯定是用宏啦,我们来看一下第一个版本:

1
2
#define foreach(container,it,type) \
    for(type::iterator it = (container).begin();it!=(container).end();++it)

示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <iostream>
#include <string>
#include <vector>
#include <set>
#include <map>
using namespace std;
 
#define foreach(container,it,type) \
    for(type::iterator it = (container).begin();it!=(container).end();++it)
 
int main(int argc, const char *argv[])
{
    set<string> s;
    s.insert("w");
    s.insert("a");
    s.insert("n");
 
 
    foreach(s,it,set<string>)
    {
        cout<<*it<<endl;
    }
 
    /*map<unsigned,string> m;
    m[0]="x";
    m[1]="w";
 
    foreach(m,it,map<unsigned,string>)
    {
        cout<<it->first<<","<<it->second<<endl;
    }*/
 
    return 0;
}

如果把注释掉的代码打开的话,就会报错,应该是宏无法处理逗号的原因。
而且调用起来还是有点繁琐对吧,python里面并没有要求传入容器类型,我们是不是也能把set这个参数省掉呢?
先来看一下这段代码:

1
2
3
typeof(10) a;
a = 100;
cout<<a<<endl;

这段代码是可以执行的,运行结果是100。从这一点出发,我们是不是能通过typeof(container)获得容器类型,然后通过typeof(container)::iterator创建遍历指针呢,我们来看第二个版本

1
2
#define foreach(container,it) \
    for(typeof(container)::iterator it = (container).begin();it!=(container).end();++it)

然而很不幸,这段代码是无法运行的,编译结果如下:

test4.cpp|21| error: expected initializer before "it"
test4.cpp|21| error: `it' was not declared in this scope
test4.cpp|34| error: expected initializer before "it"
test4.cpp|34| error: `it' was not declared in this scope

有没有办法解决呢?
有的,我们用一个曲线救国的方法!typeof(container.begin()) ,哈哈!最终代码如下:

1
2
#define foreach(container,it) \
    for(typeof((container).begin()) it = (container).begin();it!=(container).end();++it)

测试代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <vector>
#include <set>
#include <map>
using namespace std;
 
#define foreach(container,it) \
    for(typeof((container).begin()) it = (container).begin();it!=(container).end();++it)
 
int main(int argc, const char *argv[])
{
    set<string> s;
    s.insert("w");
    s.insert("a");
    s.insert("n");
 
 
    foreach(s,it)
    {
        cout<<*it<<endl;
    }
 
    map<unsigned,string> m;
    m[0]="x";
    m[1]="w";
 
    foreach(m,it)
    {
        cout<<it->first<<","<<it->second<<endl;
    }
 
    return 0;
}

输入结果如下:

a
n
w
0,x
1,w

OK!一切正常!这应该是形式比较简单的版本啦,如果各位有什么更好的建议,欢迎留言交流~
ps:
当然,其实你连it这个参数都可以省掉,但是根据pythonic的原则(好吧,我知道自己是在写C++),要简单但不能让人迷惑,所以建议还是把it这个参数保留。

同分类推荐文章

  1. 对基本有序的序列排序算法 (2026-06-11 17:46:49)
  2. Four Levels Of Customer Understanding (2026-05-22 21:00:00)
  3. 除法的意义 (2026-04-12 20:52:17)

查看更多 算法 文章 →

建议继续学习

  1. 如何学好C++语言 (累计阅读 10,448)
  2. Emacs配置C/C++-mode的代码智能提示和自动补全 (累计阅读 10,412)
  3. colortail,让 tail 命令绚丽起来 (累计阅读 10,259)
  4. 几个内存相关面试题(c/c++) (累计阅读 9,445)
  5. 关于使用STL的红黑树map还是hashmap的问题 (累计阅读 8,876)
  6. 浅析C++多线程内存模型 (累计阅读 8,803)
  7. C++ 多线程编程总结 (累计阅读 8,097)
  8. 使用gdb调试运行时的程序小技巧 (累计阅读 7,208)
  9. 在C++里写一个不能被继承的类 (累计阅读 6,580)
  10. 五个免费开源的数据挖掘软件 (累计阅读 6,528)