C++新特性
C++11的新特性有哪些
- 语法的改进
(1)统一的初始化方法
(2)成员变量默认初始化
(3)auto关键字: 允许编译器自动推断变量的类型,减少类型声明的冗余。
(4)decltype 求表达式的类型
(5)智能指针std::shared_ptr
和std::unique_ptr
.
(6)空指针nullptr
: 提供了明确表示空指针的关键字,替代了传统的NULL
。
(7)基于范围的for循环: 简化遍历容器元素的语法
(8)右值引用和move语义 引⼊右值引用和移动构造函数,允许高效地将资源从⼀个对象移动到另⼀个对象,提高性能。 - 标准库扩充(往STL里新加进⼀些模板类)
(9)无序容器(哈希表) 用法和功能同map⼀模⼀样,区别在于哈希表的效率更高
(10)正则表达式 可以认为正则表达式实质上是⼀个字符串,该字符串描述了⼀种特定模式的字符串
(11)Lambda表达式: 允许在代码中定义匿名函数
智能指针
shared_ptr
- shared_ptr的实现机制是在拷贝构造时使用同一份引用计数
(1)⼀个模板指针T* ptr
指向实际的对象
(2)⼀个引用次数
必须new出来的,不然会多个shared_ptr里面会有不同的引用次数而导致多次delete
(3)重载operator*和operator->
使得能像指针⼀样使用shared_ptr
(4)重载copy constructor
使其引用次数加一(拷贝构造函数)
(5)重载operator=(赋值运算符)
如果原来的shared_ptr已经有对象,则让其引用次数减一并判断引用是否为零(是否调用delete),然后将新的对象引用次数加一
(6)重载析构函数
使引用次数减⼀并判断引用是否为零 (是否调用delete) - 线程安全问题
(1)同⼀个shared_ptr被多个线程“读”是安全的;
(2)同⼀个shared_ptr被多个线程“写”是不安全的;
证明:在多个线程中同时对⼀个shared_ptr循环执行两遍swap。 shared_ptr的swap函数的作用就是和另外⼀个shared_ptr交换引用对象和引用计数,是写操作。执行两遍swap之后, shared_ptr引用的对象的值应该不变)
(3)共享引用计数的不同的shared_ptr被多个线程“写”是安全的。
unique_ptr
- unique_ptr “唯一”拥有其所指对象
同⼀时刻只能有⼀个unique_ptr指向给定对象,离开作⽤域时,若其指向对象,则将其所指对象销毁(默认delete)。 - 定义unique_ptr时,需要将其绑定到⼀个new返回的指针上。
- unique_ptr不⽀持普通的拷贝和赋值(因为拥有指向的对象)
但是可以拷贝和赋值⼀个将要被销毁的unique_ptr;可以通过release或者reset将指针所有权从⼀个(非const)unique_ptr转移到另⼀个unique。
weak_ptr
- weak_ptr是为了配合shared_ptr而引入的⼀种智能指针
它的最大作用在于协助shared_ptr工作,像旁观者那样观测资源的使用情况,但weak_ptr没有共享资源,它的构造不会引起指针引用计数的增加。 - 和shared_ptr指向相同内存
shared_ptr析构之后内存释放,在使用之前使用函数lock()检查weak_ptr是否为空指针。
类型推导
- auto:
auto可以让编译器在编译期就推导出变量的类型
(1)auto的使用必须马上初始化,否则无法推导出类型
(2)auto在一行定义多个变量时,各个变量的推导不能产生二义性,否则编译失败
(3)auto不能用作函数参数
(4)在类中auto不能用作非静态成员变量
(5)auto不能定义数组,可以定义指针
(6)auto无法推导出模板参数
(7)在不声明为引用或指针时,auto会忽略等号右边的引用类型和cv限定
(8)在声明为引用或者指针时,auto会保留等号右边的引用和cv属性 - decltype:
decltype则用于推导表达式类型,这里只用于编译器分析表达式的类型,表达式实际不会进行运算
decltype不会像auto⼀样忽略引用和cv属性,decltype会保留表达式的引用和cv属性
对于decltype(exp)有:- exp是表达式,decltype(exp)和exp类型相同
- exp是函数调用,decltype(exp)和函数返回值类型相同
- 其它情况,若exp是左值,decltype(exp)是exp类型的左值引用
auto和decltype的配合使用:
template<typename T, typename U>
auto add(T t, U u) -> decltype(t + u) {
return t + u;
}
右值引用
左值右值:
左值: 可以放在等号左边,可以取地址并有名字
右值: 不可以放在等号左边,不能取地址,没有名字
字符串字面值"abcd"也是左值,不是右值
++i、–i是左值,i++、i–是右值
- 将亡值
将亡值是指C++11新增的和右值引用相关的表达式
将亡值可以理解为即将要销毁的值,通过“盗取”其它变量内存空间方式获取的值,在确保其它变量不再被使用或者即将被销毁时,可以避免内存空间的释放和分配,延长变量值的生命周期,常用来完成移动构造或者移动赋值的特
殊任务 - 左值引用
左值引用就是对左值进行引用的类型,是对象的⼀个别名
并不拥有所绑定对象的堆存,所以必须立即初始化。 对于左值引用,等号右边的值必须可以取地址,如果不能取地址&#x