首页 > 代码库 > C++11较C++03的改进

C++11较C++03的改进

0  C++11


C++11又称为C++0x是新的C++语言的标准,发布于2011年。新的标准取代了2003年发布的C++03,也为C++带来了些许改进。

1 关键词auto修订


一门语言如果太啰嗦了,不仅会为阅读带来障碍,而且还是许多错误的根源。所以从C语言继承而来的关键词auto在C++11中有了新的定义,可以进行自动类型推断。
例如:
//  C++03 方式
for (std::vector<int>::const_iterator ci = v.begin(); ci != v.end(); ++ci);

//  C++11 方式
for (auto ci = v.cbegin(); ci != v.cend(); ++ci);
// 注意 cbegin() 和 cend() 返回一个 const_iterator
需要谨慎的一些应用。
auto x = 10.0;
// 如果将 `10.0‘ 变换为 `10‘, x 将变为一个整型变量
// 此处可能会给依赖于它的重载函数带来困扰
// 因此,建议1:利用auto消除繁琐而不是用来保持一致性

for (auto i = 0ul; i < v.size(); ++i);
// 此处 auto i = 0ul 相当于 `unsigned long int i=0‘
// 建议 2: 不要针对特定类型使用auto,因为那样做会给你带来不少问题

// 建议 3: 针对建议1和2,不要对常量使用auto


2  for()的循环范围


迭代操作在STL中是很常见的。C++11提供了一个专门的for函数来简化那些以begin()、end()为参数并返回迭代器的函数。这种新的方式对于C的数组同样有效。
例子:
// the C++03 way
for (std::vector<int>::iterator i = v.begin(); i != v.end(); ++i);

// the C++11 way
for (int &item: v);
// item 将从v的begin()执行到v的end()
// 注意这里的引用,它允许我们改变v中的内容

for (const int &item: v); // 这时不能改变内容,引用可以提速
for (int item: v); // 通过传值,不能改变v中内容

3 初始化列表


C++03中的容器不能像C中的数组那样利用列表初始化,这个问题在C++11中得到改进。
例如:
// C arrays
char   array1[] = {‘A‘, ‘B‘};
double array2[] = {32.0, 6.003, -0.1};

// C++03 vectors

std::vector<char> cpp03vector1;
cpp03vector1.push_back(‘A‘);
cpp03vector1.push_back(‘B‘);

std::vector<double> cpp03vector2(3);
cpp03vector2[0] = 32.0;
cpp03vector2[1] = 6.003;
cpp03vector2[2] = -0.1;

// C++11 vectors
std::vector<char>   cpp11vector1 = {‘A‘, ‘B‘};
std::vector<double> cpp11vector2 = {32.0, 6.003, -0.1};
// or...
std::vector<char>   cpp11vector3{‘A‘, ‘B‘};
std::vector<double> cpp11vector4{32.0, 6.003, -0.1};
// 注意这种方式也适用于STL中的其他容器, 不仅仅是std::vector

列表初始化也可以运用在更复杂的结构中,如下所示:
#include <map>
#include <string>
#include <vector>
#include <utility>

using namespace std;

map<string, vector<pair<string, int>>> name_languages_year {
    {"Dennis Ritchie",    {{"B",      1969}, {"C",        1973}}},
    {"Niklaus Wirth",     {{"Pascal", 1970}, {"Modula-2", 1973}, {"Oberon", 1986}}},
    {"Bjarne Stroustrup", {{"C++",    1983}}},
    {"Walter Bright",     {{"D",      1999}}}
};
// 注意为了匹配template  列表的嵌套方式。

cout << name_languages_year["Niklaus Wirth"].at(0).first << endl; // prints `Pascal‘

// adds a new entry to the map
name_languages_year["John McCarthy"] = {
    {"Lisp", 1958}
};
// 注意此处并没有显式的类型

4 C++数组


貌似这块儿是C++11添加的新的功能。
C++11提供了std::array,目的是来取代C中的数组。这是个尺寸可变的轻量级数组,使用的时候效果与std::vector差不多。
例子:
#include <array>

// C arrays
char  carray1[] = "Abc"; // caution, an unseen ‘\0‘ is added to the end
float carray2[] = {0.2f, 33.33f};

// C++ arrays
std::array<char, 3>  cpparray1{{‘A‘, ‘b‘, ‘c‘}};
std::array<float, 2> cpparray2{{0.2f, 33.33f}};
// 关注点 1: 尺寸在编译的时候推导
// 关注点 2:  数组尺寸不可变
// 关注点 3: 括号里的类型由参数列表决定


// 新旧数组的对比

std::cout << sizeof carray1 - 1; // -1 因为额外的 ‘\0‘
std::cout << sizeof carray2 / sizeof (float); // 元素的个数 != 字节数
std::cout << cpparray1.size();
std::cout << cpparray2.size();

carray2[-5] = 0.1f; // 下溢
cpparray2.at(-5) = 0.1f; // throws std::out_of_range 异常

//  C++ arrays 比 C arrays好的原因有很多,从上述代码可见一斑

5 少许修正


C++03中的一些小缺陷在C++11中得到了修正。
例如:
 set<vector<int>>在C++11中可以编译了。(注意最后两个尖括号之间没有空间哦)
2  std::string 有了front和back成员函数。
3  文件流可以接受std::string类型的文件名,意味着我们不再需要使用可笑的c_str()进行转换。
4 可以很方便的将数值想std::string进行类型转换。通过以下重载函数:
   string to_string(int) 
   string to_string(float) 
   string to_string(double) 
   ...

6 支持C++11的编译器


1 GNU C++ 编译器需要加入 -std=c++0x 来编译 C++11 代码。
2 Visual Studio 2010部分支持C++11特性。
3 Visual Studio 201X(V11)仍然只对C ++11的功能部分支持。


C++11较C++03的改进