0. 摘要
近期读了一些关于C++11标准的材料。 本篇博客将从新标准的优点、与旧版本的区别和使用方法三个角度,大致介绍我对C++11的认识。
C++11标准,原名C++0x, 是03版旧标准的更新。总结来说,新标准给我更加接近脚本语言的感觉。move语义的支持、auto关键字自动类型等新特性,使得C++11在性能和效率上比旧版本有更大优势。
我参考的博客和网页有:
http://www.csdn.net/article/2012-05-15/2805585
http://stackoverflow.com/questions/1930903/bind-vs-lambda
http://baike.baidu.com/link?url=IsEuVplXgGEw6H_tjyGU2pKIKffDw8Sry0aZd9btV8O5upyzGRofxXDviB9RI5C-XYpNY7tzAD9KAZLW8fW4n_
http://blog.csdn.net/lancelet/article/details/7220558
http://zh.wikipedia.org/wiki/C++0x
http://blogs.msdn.com/b/vcblog/archive/2011/09/12/10209291.aspx
http://msdn.microsoft.com/en-us/library/vstudio/hh567368.aspx
http://herbsutter.com/elements-of-modern-c-style/
http://en.wikipedia.org/wiki/C%2B%2B11
1. C++11 新特性概述
下面简要介绍对我来说意义较为明显的几点
1. 右值引用和move语义(move semantics)。它是优化复制的一种方式。在很多时候,深度复制是低效率的行为,而move语义将允许简单的复制指针到字符缓冲区,减少在内存配置上使用的时间。获取右值必须使用std::move<T>().举例:
1 bool is_r_value(int &&) { return true; } 2 bool is_r_value(const int &) { return false; } 3 4 void test(int && i) 5 { 6 is_r_value(i); // i 為具名變數,即使被宣告成右值也不會被認定是右值。 7 is_r_value(std::move<int&>(i)); // 使用 std::move<T>() 取得右值。 8 }
2. 类型推导:auto关键字。auto关键字可以使得我们再也不必根据右值复杂的表达式推断左值的类型。它的意义在于大大增加了代码可读性,并且节省了很多无意义的开发时间,而将数据类型的推测交给编译器来做。
举例而言,原本我们这样的表达:
1 for(vector<int>::const_iterator itr = myvec.begin(); itr != myvec.end();++itr)
可以简化为:
1 for(auto itr = myvec.begin(); itr != myvec.end();++itr)
decltype可以得到参数实例的数据类型,与auto弥补:
1 #include <vector> 2 3 int main() 4 { 5 const std::vector<int> v(1); 6 auto a = v[0];// a 为 int 类型 7 decltype(v[0]) b =0; // b 为 const int& 类型,即std::vector<int>::operator[](size_type)const 的返回类型 8 auto c =0; // c 为 int 类型 9 auto d = c; // d 为 int 类型 10 decltype(c) e; // e 为 int 类型,c 实体的类型 11 decltype((c)) f = e; // f 为 int& 类型,因为(c)是左值 12 decltype(0) g; // g为int类型,因为0是右值 13 return 0; 14 }
3. smart pointer智能指针。智能指针改善了auto_ptr的问题,使得开发过程不必担心内存释放的问题,处理内存泄露的过程得以简化。
4. 以范围为基础的for循环。for 语句将允许简单的范围迭代:第一部分定义被用来做范围迭代的变量,就像被声明在一般for循环的变量一样,其作用域仅只于循环的范围。而在":"之后的第二区块,代表将被迭代的范围。这样一来,就有了能够允许C-style数组被转换成范围概念的概念图。这可以是std::vector,或是其他符合范围概念的对象。举例:
原本的表达:
1 // circle and shape are user-defined types 2 circle* p = new circle( 42 ); 3 vector<shape*> v = load_shapes(); 4 5 for( vector<circle*>::iterator i = v.begin(); i != v.end(); ++i ) { 6 if( *i && **i == *p ) 7 cout << **i << “ is a match\n”; 8 } 9 10 for( vector<circle*>::iterator i = v.begin(); 11 i != v.end(); ++i ) { 12 delete *i; // not exception safe 13 } 14 15 delete p;
使用新标准,表达相同的过程,可以大大简化:
1 #include <memory> 2 #include <vector> 3 // ... 4 // circle and shape are user-defined types 5 auto p = make_shared<circle>( 42 ); 6 vector<shared_ptr<shape>> v = load_shapes(); 7 8 for_each( begin(v), end(v), [&]( const shared_ptr<shape>& s ) { 9 if( s && *s == *p ) 10 cout << *s << " is a match\n"; 11 } );
5. lambda表达式。lambda表达式允许如下定义:
1 [](int x, int y) { return x + y; }
lambda表达式解决了函数内部不得不使用function对象造成的繁琐问题。
6. 空指针的调整。在标准C中,0值兼顾了数值和NULL的双重语义,C++并未继承此规则,不允许将void*隐式转换为其他类型的指针。char*c = NULL;这样的表达无法直观的实现。C++11使用nullptr将0和空指针分离开:
1 char* pc = nullptr; // OK 2 int * pi = nullptr; // OK 3 int i = nullptr; // error 4 5 foo(nullptr); // 呼叫 foo(char *)
7. C++还有其他很有意义的改进,但因笔者目前接触不到这些改进的意义,仅作简单的列举:
7.1 显示虚函数重载
7.2 对POD定义的修正
7.3 强类型的枚举
7.4 模板别名
7.5 变长参数模板
7.6 正则表达式
3. 总结
C++11,相比于旧版本,主要的提升方面为:1. 语言运行时的表现强化(就是效率更高了) 2. 核心语言使用性加强(就是能写出更简洁的代码) 3. 核心语言能力提升(允许更多的如变长参数模板的表达)
4. 我的问题
lambda表达式不是很透彻..
虚函数重载不知道什么时候用?
其实,我的问题都应该会在新版本的C++Premer中得到解答,这里的疑问只有,在团队编程中,C++11如何与C++03兼容?如果一个项目里面其他的人都使用C++03,或者一个已经写好的程序使用的是C++03,如果做出C++11的改动,能否可行,或者会不会造成问题?
3. 怎么使用?(编译器支持)
新版本的C++经典教程已经对新标准进行了更新,目前主流编译器对C++11 的支持如下:
Visual Studio 2010 |
Visual Studio 2012 |
Visual Studio 2013 |
|
v2.0 |
v2.1* |
v2.1* |
|
No |
No |
No |
|
No |
No |
||
No |
No |
||
No |
No |
||
Yes |
Yes |
Yes |
|
v1.0 |
v1.0 |
v1.0 |
|
Yes |
Yes |
Yes |
|
v1.0 |
v1.1 |
v1.1 |
|
v1.0 |
v1.1** |
v1.1 |
|
Yes |
Yes |
Yes |
|
No |
No |
Yes |
|
No |
No |
No |
|
No |
No |
||
Yes |
Yes |
Yes |
|
Yes |
Yes |
Yes |
|
Partial |
Yes |
Yes |
|
No |
Yes |
Yes |
|
No |
No |
No |
|
No |
No |
No |
|
TR1 |
Partial |
Partial |
|
No |
No |
||
No |
No |
No |
|
No |
No |
Yes |
|
No |
No |
No |
|
No |
No |
No |
|
No |
No |
||
No |
No |
No |
|
No |
No |
No |
|
No |
Yes |
Yes |
|
No |
No |
||
Yes |
Yes |
Yes |
|
No |
No |
No |
|
No |
No |
No |
|
No |
No |
No |
|
Yes |
Yes |
Yes |
|
No |
Yes |
Yes |
|
Partial |
Yes |
Yes |
|
Yes |
Yes |
Yes |
|
No |
No |
No |
C++11 Core Language Features: Concurrency |
Visual Studio 2010 |
Visual Studio 2012 |
Visual Studio 2013 |
N/A |
N/A |
N/A |
|
No |
Yes |
Yes |
|
No |
Yes |
Yes |
|
No |
Yes |
Yes |
|
N/A |
N/A |
N/A |
|
No |
Yes |
Yes |
|
No |
No |
No |
|
Yes |
Yes |
Yes |
|
No |
No |
No |
|
No |
No |
No |
|
Partial |
Partial |
Partial |
|
No |
No |
No |
C++11 Core Language Features: C99 |
Visual Studio 2010 |
Visual Studio 2012 |
Visual Studio 2013 |
Partial |
Partial |
Partial |
|
Partial |
Partial |
Partial |
|
Yes |
Yes |
Yes |
|
N/A |
N/A |
N/A |