一、关键字
(1)新增关键字:thread_local、static_assert、nullptr、noexcept、decltype、constexpr、char32_t、char16_t、alignof、alignas
thread_local:实现了线程局部存储,让每个线程都独立访问数据,互不干扰;thread_local 标记的变量在每个线程里都会有一个独立的副本,是线程独占的,所以就不会有竞争读写的问题。
static_assert:静态断言,它只在编译时生效,运行阶段看不见,所以是“静态”的;
decltype:自动类型推导,不仅能够推导出值类型,还能够推导出引用类型,也就是表达式的“原始类型”,而auto只能在初始化时自动推导类型
(2)修改关键字:auto、class、default、delete
auto:根据变量初始值的类型自动为此变量选择匹配的类型,类似的关键字还有decltype;
default:明确告诉编译器,使用默认实现,编译器会为其自动生成默认的函数定义体,只需在函数声明后加上=default;
class DemoClass { public: DemoClass() = default;//明确告诉编译器,使用默认实现 ~DemoClass() = default; }
delete:明确地禁用某个函数,在成员函数声明后加 = delete,delete 关键字可用于任何函数,不仅仅局限于类成员函数;
class DemoClass { ......... public: DemoClass(const DemoClass&) = delete;//禁止拷贝构造 DemoClass& operator = (const DemoClass&) = delete;//禁止拷贝赋值 }
final:可以显式地禁用继承,防止其它人有意或者无意地产生派生类,如:
class DemoClass final { ..... }
二、新语法
(1)constexpr变量:将变量声明为constexpr类型以便由编译器来验证变量是否是一个常量表达式,比const更强的约束,这样可以得到更好的效率和安全性;
(2)内存对齐支持:alignof基本值对齐,每个元素的起始地址必须是其中一个元素最大长度的整数倍;alignas指定对象的对齐字节数,再使用alignof来查看
(3)nullptr:用于标识空指针,它可以转换成任何指针类型和bool布尔类型
(4)random_device 随机数生成器
(5)std::ref和std::cref
(6)强枚举类型(strong-type enum)
(7)lamda表达式
[=]:值捕获,捕获外部作用域中所有变量,并作为副本在函数体中使用;
[&]:引用捕获,捕获外部作用域中所有变量,并作为引用在函数体中使用。
(8)POD
(9)显式转换操作
(10)初始化列表std::initializer_list
(11)类型推导auto、decltype
(12)static_assert静态断言
(13)声明:不可见enum声明、属性声明、空声明(;)、long long类型
(14)预处理:_Pragma运算
(15)表达式:alignof查询类型的对齐要求、用户定义字面量
(16)原始字符串R"(a string)"
(17)新的for循环:for(x:range)
//遍历字符串 std::string str = “hello, world”; for(auto ch : str) { std::cout << ch << std::endl; } //遍历str,输出每个字符,同时用上auto,简直是如虎添翼。(auto也是c++11的新特性) //遍历数组 int arr[] = {1, 2, 3, 4}; for(auto i : arr) { std::cout<< i << std::endl; } //不用知道数组容器的大小,即可方便的遍历数组。 //遍历stl 容器 std::vector<std::string> str_vec = {“i”, “like”, "google”}; for(auto& it : str_vec) { it = “c++”; } //在这段程序中,可以返回引用值,通过引用可以修改容器内容。 //遍历stl map std::map<int, std::string> hash_map = {{1, “c++”}, {2, “java”}, {3, “python”}}; for(auto it : hash_map) { std::cout << it.first << “\t” << it.second << std::endl; } //遍历map返回的是pair变量,不是迭代器。
(18)数字限制numeric_limits
(19)追踪返回类型语法
(20)内联名字空间 inline namespace
(21)非受限联合体
(22)扩展的整形
(23)扩展的friend语法,可以把一些函数或类声明为“友元”,函数或类就成为该类的友元函数,在友元函数或友元类内部就可以访问该类对象的私有成员
class CCar { private: int price; friend class CDriver; //声明 CDriver 为友元类 }; class CDriver { public: CCar myCar; void ModifyCar() //改装汽车 { myCar.price += 1000; //因CDriver是CCar的友元类,故此处可以访问其私有成员 } };
三、STL容器
(1)std::array
(2)std::forward_list单向链表
(3)无序容器:std::unordered_map/std::unordered_multimap、std::unordered_set/std::unordered_multiset
(4)std::tuple元组:std::make_tuple、std::get、std::tie
(5)std::begin/std::end迭代器
(6)std::move
(7)hash
(8)emplace
四、线程
(1)std::thread
(2)std::mutex
(3)std::lock
std::lock_guard 在构造函数中进行加锁,析构函数中进行自动解锁
std::unique_lock 是通用互斥包装器,允许延迟锁定、锁定的有时限尝试、递归锁定、所有权转移和与条件变量一同使用
unique_lock比lock_guard使用更加灵活,功能更加强大,可临时解锁和再上锁,而不必等到析构时自动解锁
(4)std::call_once
(5)std::atomic
(6)std::condition_variable
wait()、notify_one()、notify_all()
(7)async
(8)volatile
(9)std::future
(10)std::thread_local
五、正则表达式
std::regex正则表达式:basic_regex、sub_match、match_results
六、智能指针
(1)std::share_ptr
std::shared_ptr使用引用计数,每一个shared_ptr的拷贝都指向相同的内存。再最后一个shared_ptr析构的时候,内存才会被释放。
shared_ptr不能通过“原始指针直接赋值”来初始化,需要通过构造函数和辅助方法来初始化
不要在函数实参中创建shared_ptr,函数参数的计算顺序在不同的编译器不同的约定下可能是不一样的,一般是从右到左,但也可能从左到右,容易出现内存泄漏
通过shared_from_this()返回this指针
(2)std::unique_ptr
unique_ptr是一个独占型的智能指针,它不允许其他的智能指针共享其内部的指针,不允许通过赋值将一个unique_ptr赋值给另一个unique_ptr
(3)std::weak_ptr
七、函数
(1)std::function
//1.保存普通函数 void printA(int a) { cout << a << endl; } std::function<void(int a)> func; func = printA; func(2); //2 //2.保存lambda表达式 std::function<void()> func_1 = [](){cout << "hello world" << endl;}; func_1(); //hello world //3.保存成员函数 class Foo{ Foo(int num) : num_(num){} void print_add(int i) const {cout << num_ + i << endl;} int num_; }; std::function<void(const Foo&,int)> f_add_display = &Foo::print_add; Foo foo(2); f_add_display(foo,1);
(2)std::bind
//可将bind函数看作是一个通用的函数适配器,它接受一个可调用对象,生成一个新的可调用对象来“适应”原对象的参数列表。 void fun_1(int x,int y,int z) { cout<<"print: x=" <<x<<",y="<< y << ",z=" <<z<<endl; } void fun_2(int &a,int &b) { a++; b++; cout<<"print: a=" <<a<<",b="<<b<<endl; } int main(int argc, char * argv[]) { //f1的类型为 function<void(int, int, int)> auto f1 = std::bind(fun_1,1,2,3); //表示绑定函数 fun 的第一,二,三个参数值为: 1 2 3 f1(); //print: x=1,y=2,z=3 auto f2 = std::bind(fun_1, placeholders::_1,placeholders::_2,3); //表示绑定函数 fun 的第三个参数为 3,而fun 的第一,二个参数分别由调用 f2 的第一,二个参数指定 f2(1,2);//print: x=1,y=2,z=3 auto f3 = std::bind(fun_1,placeholders::_2,placeholders::_1,3); //表示绑定函数 fun 的第三个参数为 3,而fun 的第一,二个参数分别由调用 f3 的第二,一个参数指定 //注意: f2 和 f3 的区别。 f3(1,2);//print: x=2,y=1,z=3 }
(3)std::bad_function_call
(4)mem_fn
八、类
(1)类型别名
使用using起别名;
(2)类成员初始化
(3)类中函数:仿函数(func)、委托构造函数、继承构造函数、移动构造函数、移动赋值运算符、并行动态初始化和析构
仿函数:它是个类,重载了()运算符;
委托构造函数:一个构造函数直接调用另一个构造函数,把构造工作“委托”出去;
继承构造函数:用using来声明继承基类的构造函数;
移动构造函数:构造函数的参数有两个&操作符, 接收的是“右值引用”的参数;对于指针,拷贝构造函数使用深拷贝,移动构造函数使用浅拷贝,拷贝构造函数的参数是一个左值引用,移动构造函数的初值是一个右值引用;
九、模板
十、性能
(1)右值引用
(2)std::move
(3)std::forward
(4)原子操作:atomic_bool、atomic_int