C++ Primer 第16章 知识点回顾

来源:互联网 发布:java使用redis统计 编辑:程序博客网 时间:2024/06/05 03:47

16.1.1 函数模板

  1. 非类型模板参数:用户提供的值必须是常量表达式,从而允许编译器在编译时实例化模板
  2. 在模板定义内,模板非类型参数是一个常量值,在需要常量表达式的地方,可以使用非类型参数,例如指定数组的大小
  3. 模板程序应该尽量减少对实参类型的要求
  4. 函数模板与类模板成员函数的定义通常放在头文件中。而类成员函数和普通函数的定义通常放在源文件,同时类定义和函数声明放在头文件中

16.1.2 类模板

  1. 与函数模板不同,编译器不能为类模板推断模板参数类型,必须使用模板实参列表。
  2. 类模板的每个实例都有自己版本的成员函数
  3. 标准库函数make_shared<T>(args);
  4. 默认情况下,一个类模板的成员函数只有当程序用到它时才进行实例化。默认情况下,对于一个实例化了的类模板,其成员只有在使用时才被实例化
  5. template<typename> class Blob;//模板声明
  6. 静态成员类外定义和初始化:template<typename T>
    size_t Foo<T>::ctr=0;

  7. 模板不是一个类型,模板实例化出的类才是类型


16.1.3 模板参数

  1. 与任何其他名字一样,模板参数会隐藏外层作用域中声明的相同名字。但是,与大多数其他上下文不同,在模板内不能重用模板参数名。由于参数名不能重用,所以一个模板参数名在一个特定模板参数列表中只能出现一次
  2. 当我们希望通知编译器一个名字表示类型时,必须使用关键字typename,而不是class**即,使用模板类型参数的类型成员时必须用typename**template<typename T>
    typename T::value_type top(const T&c)/*默认情况下,C++语言假定通过作用域运算符访问的名字不是类型,因此如果我们希望使用一个模板类型参数的类型成员,通过使用typename显示告诉编译器该名字是一个类型*/

  3. 默认模板实参Numbers<> average_precision;


16.1.4 成员模板

  1. 与类模板的普通函数成员不同,成员模板时函数模板,在类外定义成员模板时:template<typename T>//类的类型参数
    template<typename It>//构造函数的类型参数
    Blob<T>::Blob(It b,It e) {...};

16.1.5控制实例化

  1. 显示实例化:extern template class Blob<string>;//实例化声明
    template int compare(const int&,const int&);//实例化定义(实例化类模板的所有成员)

16.2.1 类型转换与模板类型参数

  1. 将实参传递给带模板类型的函数形参时,能够自动应用的类型转换只有const转换及数组或函数到指针的转换
  2. 如果函数参数类型不是模板参数吗,则对实参进行正常的类型转换

16.2.2 函数模板显式实参

  1. template<typename T1,typename T2, typename T3> T1 sum(T2,T3);
    auto val3=sum<long long>(i,lng);//long long sum(int,long)
  2. 如果我们显式指定了模板类型参数,就可以进行正常类型转换了

16.2.3 尾置返回类型与类型转换

  1. 由于尾置返回出现在参数列表之后,他可以使用函数的参数
  2. template<typename It>
    auto fcn(It beg, It end)->decltype(*beg)//得到引用类型,返回引用类型
    {
    //处理序列
    return *beg;
    }
  3. 标准库类型转换模板:remove_reference<decltype(*beg)>::type;
  4. template<typename It>
    auto fcn(It beg, It end)->typename remove_reference<decltype(*beg)>::type//使用模板类的类型成员必须使用typename
    {
    //处理序列
    return *beg;
    }

16.2.5 模板实参推断和引用

  1. 引用折叠只能引用于间接创建的引用的引用,如类型别名或模板参数
  2. 如果一个函数参数是指向模板参数类型的右值引用(如,T&&),则可以传递给他任意类型的实参。如果将一个左值传递给这样的参数,则函数参数被实例化为一个普通的左值引用(T&)(通过引用折叠)

16.2.6 理解 std::move

  1. 将一个左值static_cast到一个右值引用时允许的:虽然不能隐式地将一个左值转换为右值引用,但是我们可以用static_cast显式地将一个左值转换为一个右值引用
  2. template<typename T>
    typename remove_reference<T>::type && move(T &&t)
    {
    return static_cast<typename remove_reference<T>::type &&>(t);
    }

16.2.7 转发

  1. 如果一个函数参数是指向模板类型参数的右值引用(如T&&),它对应的实参的const属性和左值右值属相将得到保持。
  2. **通常情况下,我们使用forward传递哪些定义为模板类型参数的右值引用的函数参数。**forward返回类型是T&&。通过返回类型上的引用折叠,forward可以保持给定实参的左值右值属性
  3. 当用于一个指向模板参数类型的右值引用函数参数(T&&)时,forward会保持实参类型的所有细节

16.4 可变参数模板

  1. 模板参数包,函数参数包
  2. 包扩展:分解为构成的元素,对每个元素应用模式
  3. 转发:std::forward<Args>(args)...;
  4. 可变参数函数通常将他们的参数转发给其他函数
  5. template<typename...Args>
    void fun(Args&&...args)//将Args扩展为一个右值引用的列表
    {
    //work的实参既扩展Args又扩展args
    work(std::forward<Args>(args)...);
    }

16.5 模板特例化

  1. 一个特例化版本就是模板的一个独立的定义,在其中一个或多个模板参数被指定为特定的类型
  2. 特例化的本质是实例化一个模板,而非重载他。因此,特例化不影响函数匹配
  3. 模板及其特例化版本应该声明在同一个头文件中,所有同名模板的声明应该放在前面,然后是这些模板的特例化版本
  4. 全特例化、偏特化(部分特例化)(只有类模板特例化才可以偏特化,函数模板必须全特例化)
  5. 可以特例化类的一个成员函数
0 0
原创粉丝点击