先说下C++ 0x:
C++0x是一个新的C++标准 现行的C++标准是C++98,就是98年制定出来的 C++0x是计划在200X 制定,后来被定成C++09 美国AT&T贝尔实验室的本贾尼·斯特劳斯特卢普(Bjarne Stroustrup)博士在20世纪80年代初期发明并实现了C++(最初这种语言被称作“C with Classes”)。一开始C++是作为C语言的增强版出现的,从给C语言增加类开始,不断的增加新特性。虚函数(virtual function)、运算符重载(operator overloading)、多重继承(multiple inheritance)、模板(template)、异常(exception)、RTTI、命名空间(name space)逐渐被加入标准。1998年国际标准组织(ISO)颁布了C++程序设计语言的国际标准ISO/IEC 1488-1998。C++是具有国际标准的编程语言,通常称作ANSI/ISO C++。1998年是C++标准委员会成立的第一年,以后每5年视实际需要更新一次标准,最近一次标准更新是在2009年,目前我们一般称该标准 C++0x
C++0x 新增了许多的特性,其中Visual Studio 2010 中的 Visual C++ 编译器,即 VC10, 包含了 4 个 C++ 0x 的语言特性:lambda 表达式,自动类型推演(auto 关键字)(类似于C#的var关键字),静态断言(static_assert)和右值引用(rvalue reference)。
本人感觉新标准似乎想把C#一些特性引用过来,这种做法会导致C++越变强大还是会成为一个冗杂的庞然大物呢。哎,学习中期待理解吧!下面从这些特性的学习总结开始。
注(Lambda函数有一个函数体,但没有函数名。Lambda函数把函数指针和函数对象两者的最佳特性组合到了一起。因此,可以使用一个lambda函数来作为模板函数参数以代替一个函数对象,或者联合使用auto关键字来声明一个lambda类型的变量。)
C++0x 的语法还是比较简单。下面通过几个例子来介绍下。
先是通过 std::for_each 演示一个简单的例子:
|
|
首先,是不是发现 my_vector 的构造函数怪怪的呢。因为C++0x支持一种从C带来的初始化列表概念,
语法类似于 C 的 int array[] = {1, 2, 3, 4 ,5}。关于这个详细介绍,有机会下次再介绍
1.Lambda 的格式
对于这里的 lambda:[](int value) { std::cout << value << std::endl; }
从这里看出,lambda 是以 [] 开头的匿名函数。这个lambda 仅仅把参数打印出来,是一个 void 的函数。
对于需要返回值的 lambad,格式如下:[](int a, int b) { return a + b;}
在这里,返回值的类型是 decltype(a + b),decltype是一个新关键词,用于在编译期推导出类型。
如果想强制设定返回值类型,可以这样编写:[](int a, int b) -> int { return a + b;}
这里把返回值设置为 int 型。
2. [] 的表示方式
C++ 的 lambad 是支持闭包的。那么,是通过 [] 来表示 lambda 的变量集合,即闭包。
|
[]
//没有定义变量,使用未定义的变量会导致错误。
[a, &b]
//a以传值方式传入,b以引用方式传入
[&]
// 表示在 lambda所使用到的变量,皆以引用方式传入
[=]
// 表示在 lambda所使用到的变量,皆以传值方式传入
[&, a]
//表示 a 以传值方式传入,其他都是以引用方式传入
[=, &a]
// 表示 a 以引用方式传入,其他都是以传值方式传入
如果企图修改以值传入的变量,则编译的时候会报错(gcc 4.5)
|
下面来看看一个闭包的lambda例子:
|
|
这里的输出结果是: total:5
3.涉及 this 指针的使用
在成员函数中涉及到对象的 this 指针,必须显式地传入lambda函数,否则成员函数的lambda函数无法使用任何对象的变量或者函数,格式如下:
[this]() { this->call_function(); }
auto 这个关键字来自 C++ 98 标准。在 C++ 98 中它没有什么作用,C++ 0x 中“借用”它来作为自动类型推演(automatic type deduction)。当 auto 出现在声明中时,它表示“请用初始化我的表达式类型作为我的类型”,例如下面代码:
#include <iostream> #include <map> #include <ostream> #include <regex> #include <string>
using namespace std; using namespace std::tr1;
int main() { map<string, string> m;
const regex r("(\\w+) (\\w+)");
for (string s; getline(cin, s); ) { smatch results;
if (regex_match(s, results, r)) { m[results[1]] = results[2]; } }
for (auto i = m.begin(); i != m.end(); ++i) { cout << i->second << " are " << i->first << endl; }
运行结果如下:
cute kittens ugly puppies evil goblins ^Z kittens are cute goblins are evil puppies are ugly
上面例子中i的类型在编译时推演为 map::iterator, 有了 auto 关键字你再也不用写又长又烦的代码了。(注意 m.begin() 返回类型是 iterator, 而不是 const_iterator, 因为这里的 m 并不是 const。C++0x 中的 cbegin() 能够解决这个问题,它返回 non-const 容器的 const 迭代器。)