先看一段使用了std::list的代码:
std::list<int> array; for(int i = 0; i < 10; i++) { array.push_back(i); } for (std::list<int>::iterator it = array.begin(); it != array.end(); ++it) { (*it) += 1; } for (std::list<int>::iterator it = array.begin(); it != array.end(); ++it) { printf("%d\t", *it); }
我们观察这段代码。首先,它是正确的,没什么错误,但看起来太臃肿了。本来我要完成每个元素的值加1关键的代码只有一行
(*it) += 1;
现在却要写上四行,再加一个空行五行。还有,“it”的类型声明也是一个麻烦事,写的长不说还要随时记住类型,修改时也麻烦。总之写得痛苦看着不爽,所以需要优化。
STL中提供了for_each算法,这是首先想到的优化方法,一起来看看效果:
std::for_each(array.begin(), array.end(), _AutoPlus(1)); std::for_each(array.begin(), array.end(), _PrintArrayItem());
还不错是吧,且慢,_AutoPlus和_PrintArrayItem是什么东东?好吧,看定义:
struct _PrintArrayItem { void operator()(int n) { printf("%d\t", n); } }; struct _AutoPlus { void operator()(int& n) { n += nVal; } _AutoPlus(int n) : nVal(n) {} int nVal; };
原来是两个仿函数,用以封装对list元素的操作。看起来挺酷的,数数代码行吧——晕了,比原来的还多。看来这种方法只适用多个地方重复相同操作的情况,因为只有这种情况下定义仿函数才觉得值。那么怎么办呢?
我为上面这个事情郁闷了很久,直到有一天偶然知道了VS2010已经支持C++ 0x的新特性lambda表达式,不由得心中一喜,赶快试试:
// 用lambda表达式实现累加,注意参数声明是int& std::for_each(array.begin(), array.end(), [](int& n) { n++; }); // 用lambda表达式实现打印输出 std::for_each(array.begin(), array.end(), [](int n){ printf("%d\t", n); });
“[]”开头的部分就表示lambda表达式了,真的是个不错的特性,现在代码简洁多了完全达到预期。lambda表达式实质上是生成了一个临时的匿名仿函数对象,不要小看匿名这两个字,有了它我们就不需要提前写麻烦的仿函数声明,代码逻辑也就不会分散到各个角落从而造成理解上的障碍。
对复杂一点的操作我们可能希望先把lambda表达式写好然后当作参数使用,这时候auto关键字就派上用场了。auto关键字用于自动类型推断,我们可以把一个lambda表达式赋值给一个auto型的变量,这样就不必为lambda表达式的类型费心了:
auto _AutoIncr = [](int& n) { n++; }; auto _PrintItem = [](int n){ printf("%d\t", n); }; std::for_each(array.begin(), array.end(), _AutoIncr); std::for_each(array.begin(), array.end(), _PrintItem);
是不是很酷啊,呵呵。
关于VS2010对C++ 0x新特性的支持可以参考这篇文章: