• 文章
  • C++11 相较于 C++03 的改进
发布
2011 年 9 月 30 日 (最后更新:2011 年 11 月 12 日)

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

评分:4.3/5 (430 票)
*****

关于 C++11

C++11,也称为 C++0x,是 C++ 语言的新标准,于 2011 年底发布。
它取代了 2003 年发布的旧 C++03 标准。
当然,它带来了对旧标准的改进,本文将概述其中一些。

重塑的 auto 关键字

冗长是坏的,主要是因为它使你的代码不那么清晰。
因此,auto 关键字,作为 C 的遗留物,在 C++11 中获得了新的含义:自动类型推导。

示例
1
2
3
4
5
6
// the C++03 way
for (std::vector<int>::const_iterator ci = v.begin(); ci != v.end(); ++ci);

// the C++11 way
for (auto ci = v.cbegin(); ci != v.cend(); ++ci);
// notice the dedicated cbegin() and cend() member functions which return a const_iterator 


糟糕的例子
1
2
3
4
5
6
7
8
9
10
auto x = 10.0;
// if a newbie programmer changes `10.0' to `10', x becomes an integral type
// and code depending on it to be a floating point type will fail
// advice 1: use auto against verbosity, not consistency

for (auto i = 0ul; i < v.size(); ++i);
// this is just a clever way of writing `unsigned long int i=0'
// advice 2: don't use auto if you specify the type, it defeats its purpose

// advice 1+2=3: don't use auto with constants 


基于范围的 for()

遍历 STL 容器的内容是一项非常常见的操作。
C++11 现在提供了一个专门的 for(),它可以遍历任何具有 begin()end() 成员函数,并且这些函数返回预期迭代器的对象。
它也可以用于普通的 C 数组。

示例
1
2
3
4
5
6
7
8
9
10
// 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 will become, in order, all the things stored in v
// notice how we're referencing the item, that allows us to change it

for (const int &item: v); // can't change item, we reference it for speed
for (int item: v); // can't change item, we're passing it by value 


初始化列表

C++03 中的容器不像经典的 C 风格数组那样可以“自然地”初始化。这种情况已经改变。

示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 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};
// notice that this works for all other containers as well, not just std::vector 


初始化列表也可以用于更复杂的结构。

示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#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}}}
};
// notice how the lists are nested to match the templates' parameters

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}
};
// notice the lack of explicit types 


C++ 数组


这更多的是一种补充而不是改进,但我还是决定把它包含在文章中。
C++11 提供了 std::array,其目的是取代 C 数组。它是动态大小的 std::vector 的一个固定大小的轻量级替代品。

示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#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}};
// observation 1: the size must be deducible at compile time
// observation 2: the array cannot be resized
// observation 3: the inner braces are due to the nature of initializer lists,
//  think of it as one list per template parameter

// array test drive: the old versus the new

std::cout << sizeof carray1 - 1; // -1 because of the extra '\0'
std::cout << sizeof carray2 / sizeof (float); // because number of elements != number of bytes
std::cout << cpparray1.size();
std::cout << cpparray2.size();

carray2[-5] = 0.1f; // do the moonwalk!
cpparray2.at(-5) = 0.1f; // throws std::out_of_range exception

// of course there are more reasons why C++ arrays are better than C arrays
// but this example code section is already too big... 


小的修正

C++03 有一堆小错误和设计缺陷,这些在 C++11 中得到了修复。
  • 诸如 set<vector<int>> 之类的东西终于可以编译了。
    请注意最后两个尖括号之间的空格缺失。

  • std::string 现在具有 front()back() 成员函数。

  • 文件流现在可以接受 std::string 作为文件名。
    这意味着可以减少对那个可笑的 c_str() 成员函数的使用。

  • 现在可以通过使用重载函数轻松地将数值转换为 std::string
    string to_string(int)
    string to_string(float)
    string to_string(double)
    ...

C++11 的编译器支持

…… 情况还不错。但还需要一两年时间来稳定。

GNU C++ 编译器需要命令行参数 -std=c++0x 来编译 C++11 代码。

Microsoft Visual Studio 2010 对 C++11 功能有部分支持,开箱即用。
Microsoft Visual Studio 201x (v11) 对 C++11 功能仍只有部分支持。