C++八股文(四)
1. C++11 的新特性有哪些
C++新特性主要包括包含语法改进和标准库扩充两个方面,主要包括以下11点:
-
语法的改进
(1)统一的初始化方法
(2)成员变量默认初始化
(3)auto关键字 用于定义变量,编译器可以自动判断的类型(前提:定义一个变量时对其进行初始化)
(4)decltype 求表达式的类型
(5)智能指针 shared_ptr
(6)空指针 nullptr(原来NULL)
(7)基于范围的for循环
(8)右值引用和move语义 让程序员有意识减少进行深拷贝操作
-
标准库扩充(往STL里新加进一些模板类,比较好用)
(9)无序容器(哈希表) 用法和功能同map一模一样,区别在于哈希表的效率更高
(10)正则表达式 可以认为正则表达式实质上是一个字符串,该字符串描述了一种特定模式的字符串
(11)Lambda表达式
具体展开:
-
统一的初始化方法
C++98/03 可以使用初始化列表(initializer list)进行初始化:
int i_arr[3] = { 1, 2, 3 }; long l_arr[] = { 1, 3, 2, 4 }; struct A { int x; int y; } a = { 1, 2 };
但是这种初始化方式的适用性非常狭窄,只有上面提到的这两种数据类型可以使用初始化列表。在 C++11 中,初始化列表的适用性被大大增加了。它现在可以用于任何类型对象的初始化,实例如下:
class Foo { public: Foo(int) { } private: Foo(const Foo &); }; int main(void) { Foo a1(123); Foo a2 = 123; //error: 'Foo::Foo(const Foo &)' is private Foo a3 = { 123 }; Foo a4 { 123 }; int a5 = { 3 }; int a6 { 3 }; return 0; }
在上例中,a3、a4 使用了新的初始化方式来初始化对象,效果如同 a1 的直接初始化。a5、a6 则是基本数据类型的列表初始化方式。可以看到,它们的形式都是统一的。这里需要注意的是,a3 虽然使用了等于号,但它仍然是列表初始化,因此,私有的拷贝构造并不会影响到它。a4 和 a6 的写法,是 C++98/03 所不具备的。在 C++11 中,可以直接在变量名后面跟上初始化列表,来进行对象的初始化。
-
成员变量默认初始化
好处:构建一个类的对象不需要用构造函数初始化成员变量。
//程序实例 #include<iostream> using namespace std; class B { public: int m = 1234; //成员变量有一个初始值 int n; }; int main() { B b; cout << b.m << endl; return 0; }
-
auto关键字
用于定义变量,编译器可以自动判断的类型(前提:定义一个变量时对其进行初始化)。
//程序实例 #include <vector> using namespace std; int main(){ vector< vector<int> > v; vector< vector<int> >::iterator i = v.begin(); return 0; }
可以看出来,定义迭代器 i 的时候,类型书写比较冗长,容易出错。然而有了 auto 类型推导,我们大可不必这样,只写一个 auto 即可。
-
decltype 求表达式的类型
decltype 是 C++11 新增的一个关键字,它和 auto 的功能一样,都用来在编译时期进行自动类型推导。
(1)为什么要有decltype
因为 auto 并不适用于所有的自动类型推导场景,在某些特殊情况下 auto 用起来非常不方便,甚至压根无法使用,所以 decltype 关键字也被引入到 C++11 中。
auto 和 decltype 关键字都可以自动推导出变量的类型,但它们的用法是有区别的:
auto varname = value; decltype(exp) varname = value;
其中,varname 表示变量名,value 表示赋给变量的值,exp 表示一个表达式。
auto 根据"=“右边的初始值 value 推导出变量的类型,而 decltype 根据 exp 表达式推导出变量的类型,跟”="右边的 value 没有关系。
另外,auto 要求变量必须初始化,而 decltype 不要求。这很容易理解,auto 是根据变量的初始值来推导出变量类型的,如果不初始化,变量的类型也就无法推导了。decltype 可以写成下面的形式:
decltype(exp) varname;
(2)代码示例
// decltype 用法举例 int a = 0; decltype(a) b = 1; //b 被推导成了 int decltype(10.8) x = 5.5; //x 被推导成了 double decltype(x + 100) y; //y 被推导成了 double
-
智能指针 shared_ptr
和 unique_ptr、weak_ptr 不同之处在于,多个 shared_ptr 智能指针可以共同使用同一块堆内存。并且,由于该类型智能指针在实现上采用的是引用计数机制,即便有一个 shared_ptr 指针放弃了堆内存的“使用权”(引用计数减 1),也不会影响其他指向同一堆内存的 shared_ptr 指针(只有引用计数为 0 时,堆内存才会被自动释放)。
#include <iostream> #include <memory> using namespace std; int main() { //构建 2 个智能指针 std::shared_ptr<int> p1(new int(10)); std::shared_ptr<int> p2(p1); //输出 p2 指向的数据 cout << *p2 << endl; p1.reset();//引用计数减 1,p1为空指针 if (p1) { cout << "p1 不为空" << endl; } else { cout << "p1 为空" << endl; } //以上操作,并不会影响 p2 cout << *p2 << endl; //判断当前和 p2 同指向的智能指针有多少个 cout << p2.use_count() << endl; return 0;