[学习笔记]现代c++11/14/17总结

语言可用性的强化

常量

  1. nullptr
    传统c++会把NULL、0解析成一种东西,有些编译器会把NULL定义成((void*)0)或者0。使用NULL调用函数会导致c++重载特性混乱。比如:
    void foo(char*),
    void foo(int)
    foo(NULL)会调用foo(int).
    C++11 引入了 nullptr 关键字,专门用来区分空指针、0。而 nullptr 的类型为 nullptr_t,能够隐式的转换为任何指针或成员指针的类型,也能和他们进行相等或者不等的比较。

  2. constexpr
    C++ 标准中数组的长度必须是一个常量表达式。constexpr关键字可以修饰函数和变量,作用是把编译时就把这些表达式直接优化并植入到程序运行时。

变量及初始化

  1. if/switch 变量声明强化
    c++17后能够在if/switch语句中定义局部变量。比如:if(int i=0;i>=0){…}。
  2. 初始化列表
    c++11加入std::initializer_list。初始化列表可以使用在类构造函数和普通函数上。
    void foo(std::initializer_list list) {…}
    Foo foo2 {3, 4};
  3. 结构化绑定
    c++11加入。
#include 
#include 

std::tuple<int, double, std::string> f() {
    return std::make_tuple(1, 2.3, "456");
}

int main() {
    auto [x, y, z] = f();
    std::cout << x << ", " << y << ", " << z << std::endl;
    return 0;
}

类型推导

  1. auto
    auto不能用于函数传参,不能推导数组类型。
  2. decltype
    计算某个表达式的类型。
  3. 尾返回类型推导
    C++11:尾返回类型(trailing return type)
template<typename T, typename U>
auto add2(T x, U y) -> decltype(x+y){
    return x + y;
}

C++14: 直接返回类型推导

template<typename T, typename U>
auto add3(T x, U y){
    return x + y;
}
  1. decltype(auto)
    对转发函数或封装的返回类型进行推导。
std::string foo(){...}
decltpye(auto) foo1(){
	return foo();
}
  1. if constexpr
    C++17 将 constexpr 这个关键字引入到 if 语句中,允许在代码中声明常量表达式的判断条件。
  2. 区间for迭代
    C++11加入:for(auto item:arr){…}

模板

  1. 外部模板
    C++11加入。显式的通知编译器何时进行模板的实例化。extern template class std::vector;
  2. 尖括号">"
    C++11加入。vector> a;
  3. 类型别名模板
    typedef无法为模板定义一个别名,因此C++11加入using,支持对模板定义别名。using TrueDarkMagic = MagicType;
  4. 变长参数模板
    C++11 加入了新的表示方法, 允许任意个数、任意类别的模板参数,同时也不需要在定义时将参数的个数固定:template class Magic;。个数为0的模板参数也可以使用sizeof…()计算参数个数
    变参模板展开
    C++17加入,作用是展开变长模板参数。
    初始化列表展开
  5. 折叠表达式
    C++17加入。void foo(int …t);
  6. 非类型模板参数推导
    C++11加入:template
    C++17加入:template void foo();

面对对象

  1. 委托构造
    C++11加入,使得在同一个类中的构造函数可以调用另一个构造函数。
  2. 继承构造
    C++11加入,使用using继承构造函数。
  3. 显式虚函数重载
    C++11加入override 和 final,防止意外重载虚函数。override告诉编译器这是一个重载函数,编译器将检查基函数是否存在这样的虚函数。final防止类继续被继承,终止虚函数继续重载。
  4. 显式禁用默认函数
    C++11加入=default和=delete。
  5. 强类型枚举
    C++11 引入了枚举类(enumeration class),并使用 enum class 的语法进行声明。

语言运行期的强化

Lambda表达式

  1. 基础
    基本语法:

     [捕获列表](参数列表) mutable(可选) 异常属性 -> 返回类型 {
     // 函数体
     }
    

    值捕获:[value]{…}。捕获并复制函数上层上下文的参数,类似于函数传值。
    引用捕获:[&value]{…}。与值捕获类似,不同的是捕获的是引用
    隐式捕获:[=]值捕获,[&]引用捕获,让编译器推导捕获列表。
    表达式捕获:C++14加入,允许右值捕获。被声明的捕获变量会根据表达式判断,判断方式与auto相同。[v1=1](int x,int y){return v1+x+y};_

  2. 泛型Lambda
    auto不能用在函数参数上,因为这会与模板功能产生冲突。C++14开始,Lambda函数的形参可以是auto。

函数对象包装器

  1. std::function
    是一种通用、多态的函数封装。
  2. std::bind和std::placeholder
    std::bind 则是用来绑定函数调用的参数的。std::placeholder用来对参数占位、

右值引用

左值(lvalue, left value),顾名思义就是赋值符号左边的值。准确来说, 左值是表达式(不一定是赋值表达式)后依然存在的持久对象。

右值(rvalue, right value),右边的值,是指表达式结束后就不再存在的临时对象。
纯右值(prvalue, pure rvalue),纯粹的右值,要么是纯粹的字面量,例如 10, true; 要么是求值结果相当于字面量或匿名临时对象,例如 1+2。非引用返回的临时变量、运算表达式产生的临时变量、 原始字面量、Lambda 表达式都属于纯右值。
将亡值(xvalue, expiring value),是 C++11 为了引入右值引用而提出的概念(因此在传统 C++ 中, 纯右值和右值是同一个概念),也就是即将被销毁、却能够被移动的值。

移动语义

默认的移动操作,必须先复制再析构,造成了大量浪费资源的操作。

完美转发

无论模板参数是什么类型的引用,当且仅当实参类型为右引用时,模板参数才能被推导为右引用类型。std::forward 和 std::move 一样,没有做任何事情,std::move 单纯的将左值转化为右值, std::forward 也只是单纯的将参数做了一个类型的转换,从现象上来看, std::forward(v) 和 static_cast(v) 是完全一样的。

无序容器

C++11 引入了两组无序容器:std::unordered_map/std::unordered_multimap 和 std::unordered_set/std::unordered_multiset。

元组

  1. 基本操作
    关于元组的使用有三个核心的函数:
    std::make_tuple: 构造元组
    std::get: 获得元组某个位置的值
    std::tie: 元组拆包

  2. 运行时索引
    使用 std::variant<>(C++ 17 引入),提供给 variant<> 的类型模板参数 可以让一个 variant<> 从而容纳提供的几种类型的变量(在其他语言,例如 Python/JavaScript 等,表现为动态类型)

  3. 元组合并与遍历
    合并两个元组,这可以通过 std::tuple_cat 来实现。

智能指针与内存管理

  1. RAII与引用计数
    C++11 引入了智能指针的概念,使用了引用计数的想法,让程序员不再需要关心手动释放内存。

  2. std::shared_ptr
    std::shared_ptr 是一种智能指针,它能够记录多少个 shared_ptr 共同指向一个对象,从而消除显式的调用 delete,当引用计数变为零的时候就会将对象自动删除。
    std::make_shared 就能够用来消除显式的使用 new,所以std::make_shared 会分配创建传入参数中的对象, 并返回这个对象类型的std::shared_ptr指针。

  3. std::unique_ptr
    std::unique_ptr 是一种独占的智能指针,它禁止其他智能指针与其共享同一个对象,从而保证代码的安全。

  4. std::weak_ptr
    std::weak_ptr是一种弱引用(相比较而言 std::shared_ptr 就是一种强引用)。弱引用不会引起引用计数增加。

你可能感兴趣的:(学习笔记,c++,编程语言)