分享

掀起C++ 11的神秘面纱(1)

 无云666 2015-03-04

【51CTO 6月21日外电头条】C++之父Bjame Stroustrup最近说C++11就像一个新语言,的确,C++11核心已经发生了巨大的变化,它现在支持Lambda表达式,对象类型自动推断,统一的初始化语法,委托构造函数,deleted和defaulted函数声明nullptr,以及最重要的右值引用。

 

【编辑推荐】

C++0x FAQ中文版(http://imcc./logs/106046323.html

C++11标准库也使用新的算法,新的容器类,原子操作,类型特征,正则表达式,新的智能指针,async()函数和多线程库进行了改造。

C++11的新内核和库特性完整列表请移步这里(http://www2.research./~bs/C++0xFAQ.html) C++标准在1998年获得通过后,有两位委员会委员预言,下一代C++标准将“肯定”包括内置的垃圾回收器(GC),但可能不会支持多线程,因为定义一个可移植的线程模型涉及到的技术太复杂了,13年后,新的C++标准C++11也接近完成,你猜怎么着?让那两位委员没想到的是,本次更新还是没有包括GC,但却包括了一个先进的线程库。

在这篇文章中,我将介绍C++11标准中发生的最大变化,以及为什么应该引起注意,正如你将看到的,线程库不是唯一的变化,新标准采纳了数十位专家的意见,使C++变得更有意义。正如Rogers Cadenhead指出的那样,它们就像迪斯科、宠物石和长胸毛的奥运游泳选手一样不可思议。

首先,让我们看看C++11核心语言的一些突出特性。

Lambda表达式

Lambda表达式允许你在本地定义函数,即在调用的地方定义,从而消除函数对象产生的许多安全风险,Lambda表达式的格式如下:

  1. [capture](parameters)->return-type {body} 

[]里是函数调用的参数列表,表示一个Lambda表达式的开始,让我们来看一个Lambda例子:

假设你想计算某个字符串包含多少个大写字母,使用for_each()遍历一个char数组,下面的Lambda表达式确定每个字母是否是大写字母,每当它发现一个大写字母,Lambda表达式给Uppercase加1,Uppercase是定义在Lambda表达式外的一个变量:

  1. int main()  
  2. {  
  3.    char s[]="Hello World!";  
  4.    int Uppercase = 0; //modified by the lambda  
  5.    for_each(s, s+sizeof(s), [&Uppercase] (char c) {  
  6.     if (isupper(c))  
  7.      Uppercase++;  
  8.     });  
  9.  cout<< Uppercase<<" uppercase letters in: "<< s<<endl;  

这是因为,如果你定义的函数主体被放置在另一个函数调用内部,[&Uppercase]中的“&”记号意味着Lambda主体获得一个Uppercase的引用,以便它能修改,如果没有这个特殊记号,Uppercase将通过值传递,C++11 Lambda表达式也包括成员函数构造器。

自动类型推断和decltype

在C++03中,在声明对象时,你必须指定对象的类型,然而,在许多情况下,对象的声明包括在初始化代码中,C++11利用了这个优势,允许你声明对象时不指定类型:

  1. auto x=0; //x has type int because 0 is int  
  2. auto c='a'; //char  
  3. auto d=0.5; //double  
  4. auto national_debt=14400000000000LL;//long long 

相反,你可以声明下面这样的迭代器:

  1. void fucn(const vector<int> &vi)  
  2. {  
  3. vector<int>::const_iterator ci=vi.begin();  
  4. }  

关键字auto不是什么新生事物,我们早已认识,它实际上可以追溯到前ANSI C时代,但是,C++11改变了它的含义,auto不再指定自动存储类型对象,相反,它声明的对象类型是根据初始化代码推断而来的,C++11删除了auto关键字的旧有含义以避免混淆,C++11提供了一个类似的机制捕捉对象或表达式的类型,新的操作符decltype需要一个表达式,并返回它的类型。

  1. const vector<int> vi;  
  2. typedef decltype (vi.begin()) CIT;  
  3. CIT another_const_iterator;  

统一初始化语法

C++至少有4个不同的初始化符号,有些存在重叠,括号初始化语法如下:

  1. std::string s("hello");  
  2. int m=int(); //default initialization  

在某些情况下,你也可以使用“=”符号进行初始化:

  1. std::string s="hello";  
  2. int x=5;  

对于POD聚合,你还可以使用大括号:

  1. int arr[4]={0,1,2,3};  
  2. struct tm today={0};  

最后,构造函数使用成员进行初始化:

  1. struct S {  
  2.  int x;  
  3.  S(): x(0) {} };  

显然,这么多种初始化方法会引起混乱,对新手来说就更痛苦了,更糟糕的是,在C++03中,你不能初始化POD数组成员,POD数组使用new[]分配,C++11使用统一的大括号符号清理了这一混乱局面。

  1. class C  
  2. {  
  3. int a;  
  4. int b;  
  5. public:  
  6.  C(int i, int j);  
  7. };  
  8.  
  9. C c {0,0}; //C++11 only. Equivalent to: C c(0,0);  
  10.  
  11. int* a = new int[3] { 1, 2, 0 }; /C++11 only  
  12.  
  13. class X {  
  14.   int a[4];  
  15. public:  
  16.   X() : a{1,2,3,4} {} //C++11, member array initializer  
  17. }; 

关于容器,你可以和一长串的push_back()调用说再见了,在C++11中,你可以直观地初始化容器:

  1. // C++11 container initializer  
  2. vector vs<string>={ "first", "second", "third"};  
  3. map singers =  
  4.   { {"Lady Gaga", "+1 (212) 555-7890"},  
  5.     {"Beyonce Knowles", "+1 (212) 555-0987"}};  

类似地,C++11支持类似的数据成员类内初始化:

  1. class C  
  2. {  
  3.  int a=7; //C++11 only  
  4. public:  
  5.  C();  
  6. };  

内容导航
 第 1 页:C++11标准的变化  第 2 页:Deleted和Defaulted函数
 第 3 页:统一初始化语法

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多