C++模版基础

简介: C++模版基础

代码地址

git@github.com:CHENLitterWhite/CPPWheel.git

专栏介绍

本专栏会持续更新关于STL中的一些概念,会先带大家补充一些基本的概念,再慢慢去阅读STL源码中的需要用到的一些思想,有了一些基础之后,再手写一些STL代码。

(如果你有喜欢一些底层封装,执着于造轮子,我想这个一期不错的专栏)

函数模版

  说下自己的理解,C++通过加入参数化编程可以有效的降低软件的成本。

  •   优势

  1.通过模版机制,在需要修改代码的时候,对于相同参数的修改不需要大批量修改,降低出错概率。

  2.支持泛型编程,总的来说还是为了大量的、无意义的工作。这些工作只是因为数据类型的不同,其算法或者业务逻辑相同时,不需要键入多份代码。

  •    特征

   1.类型严格匹配是模版函数调用的先决条件

   2.函数模板不提供隐式类型转化,因此必须严格按照T --> 为了方便理解,把T看做占位符

   3.当模板函数和普通函数都符合调用规则时,优先使用普通函数,因为普通函数在编译期间就生成了函数体,而模板函数的生成需要在调用的时候。--> 这一点很重要,模版函数会进行二次编译来确定具体的类型,可以理解为替换占位符T

   4.编译器在处理函数模版的时候能够生成任意类型的函数,根据调用的时机产生不同的函数,编译器会对函数模板进行二次编译。这个参数化编程的基础,也是成为编译时多态的由来。--> 在声明的地方对模板代码本身进行编译,在调用的地方对参数化以后的具体调用进行编译。这也导致了,在使用模板函数时,需要使用hpp文件。

demo.h

demo.cpp

main.cpp

解释下:

       我们现在知道了,模版函数会进行两次编译。在第一次编译的时候,如果将声明和定义分开,编译不通过,无法确定类型。在运行的时候才会进行类型的绑定。

       我们可以声明和定义都写在 .h中

demo.h

可以顺利编译成功,验证了我们的想法。

-------------------------------------------------------------------------------------------------------------------------

    这里引出一个问题,虽然写在.h是可以的,但是这样破坏了C++将.h和.cpp分离编程风格的原则,似乎有些不妥。

hpp文件的由来

   .h和.cpp分离之后模版第二次编译时会失败,虽然可以放到.h里面,但是这样破坏了.h和.cpp的传统。

命名空间的重要性

   当使用模版时,当模版函数相同时,在调用的时候只会使用一个模板函数。当项目比较大时,通常会通过命名空间将其隔开,这很容易理解。在项目中其实用的不多,通常情况下会以类作为空间的区分。

类模版

   类模板用于实现类所需数据的类型参数化。类模板在表示数组、表、图等数据结构时显得特别重要。这些数据结构的表示和算法不受所包含的元素类型的影响。道理跟函数模版一样,减少重复编程,降低代码错误发生的概率,降低代码冗余。

右值引用

  [为什么需要右值引用?说白了是为了效率,对于右值引用而言,常用的场景在转义语义上,减少拷贝过程,提高程序的效率]

  左值 --> 可以出现在赋值运算符的左边,往往代表的是一个存储空间(本质上就是一个块有名字的内存块)

  右值 --> 就是我们所谓是数据,其实也不完全能这样描述。对于右值而言,他是具有存储空间的,只不过这个过程很短暂,只是用在计算过程中的,我们无法获取到,仅仅在某个表达式运行过程中存在。【通常右值是一个和运算过程相匹配的临时对象,这个临时对象在所对应的语句执行完毕之后,就销毁了。所以,我们无法从语法层面上直接访问

 

  说人话:

  左值 --> 是一个有名字的,有固定地址的对象

  右值 --> 是一个匿名的,没有固定地址的对象

程序中的体现:

int &a = x;          -->  左值引用 [左值引用替代值传递,减少拷贝]、

int &&a = x + y;  -->  右值引用[通过&&,形成的语法叫做右值引用,使得右值变成了一个与左值完全相同的持久对象]

右值引用:我们知道浅拷贝会带来资源二次释放问题,但是深拷贝在一些临时资源时又是没有必要的,这是右值引用拷贝构造函数的很大意义,即可以避免二次释放问题,又减少了数据拷贝的过程。

整个过程,看似很简单,但是对于一个追求性能和简洁的语言,是一个很大的进步。

右值引用 -- 完美转发(完美的按照我们的要求进行左值和右值转发)

这里我们需要通过move和forward函数来实现左值和右值的转化。

#include <iostream>
using namespace std;
void Func(int &x)
{
    cout << "左值" <<endl;
}
void Func(int &&x)
{
    cout << "右值" << endl;
}
void Func(const int &x)
{
    cout << "左值常" << endl;
}
void Func(const int &&x)
{
    cout << "右值常" << endl;
}
template<typename T>
void FuncT(T &&a)
{
    Func(std::forward<T> (a));
}
int main()
{
    int a = 10;
    FuncT(10);  // 右值
    FuncT(a);   // 左值
    FuncT(move(a)); // 右值
    const int b = 8;
    FuncT(b);   // 左值常
    FuncT(move(b)); // 右值常
    return 0;
}

可以看到按照我们要求进行参数匹配...这就是所谓的完美转发,笑死

相关文章
|
7月前
|
存储 算法 编译器
【C++入门到精通】C++入门 —— 模版(template)
模板是C++中的一种编程工具,它允许使用通用代码来定义函数和类,以适应多种类型或值的需求,从而实现代码的复用和泛化。模板实质上是一种参数化的类型或值的规范。
91 0
|
7月前
|
算法 安全 编译器
【C++】从零开始认识泛型编程 — 模版
泛型编程是C++中十分关键的一环,泛型编程是C++编程中的一项强大功能,它通过模板提供了类型无关的代码,使得C++程序可以更加灵活和高效,极大的简便了我们编写代码的工作量。
82 3
|
2月前
|
Unix 编译器 Linux
C++之模版进阶篇(下)
C++之模版进阶篇(下)
49 0
|
2月前
|
编译器 C++
C++之模版进阶篇(上)
C++之模版进阶篇(上)
19 0
|
2月前
|
编译器 C语言 C++
C++之模版初阶
C++之模版初阶
16 0
|
2月前
|
存储 编译器 C++
【C++模版初阶】——我与C++的不解之缘(七)
【C++模版初阶】——我与C++的不解之缘(七)
|
6月前
|
C++
C++中函数模版与类模版
C++中函数模版与类模版
57 4
|
7月前
|
算法 安全 编译器
C++:模版初阶 | STL简介
C++:模版初阶 | STL简介
|
7月前
|
算法 安全 编译器
C++:模版进阶 | Priority_queue的模拟实现
C++:模版进阶 | Priority_queue的模拟实现
|
7月前
|
机器学习/深度学习 存储 算法
C++ 模版函数介绍:介绍模版函数的基本概念、用法和作用
C++ 模版函数介绍:介绍模版函数的基本概念、用法和作用
75 1