关于 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 功能仍只有部分支持。