#学习自用#
模板
模板解决代码复用
我们看一个简单的例子。
#include<iostream>
#include<string>
using namespace std;
void print(string str)
{
cout << str << endl;
}
void print(int str)
{
cout << str << endl;
}
void print(float str)
{
cout << str << endl;
}
int main()
{
print("odd");
print(1);
print(3.5f);
}
要打印不同的类型,就要传入不同的参数,可以用函数重载实现,但是这样复制粘贴的代码看起来很臃肿,像这种几个代码相同,只是传入的参数不同的函数就可以用模板来实现。
#include<iostream>
#include<string>
using namespace std;
template<typename T>
void print(T value)
{
cout << value << endl;
}
int main()
{
print("odd");//print<string>("odd")
print(1);
print(3.5f);
cin.get();
}
void print(T value) 只是模板并不是真正的函数,当我们在main函数中调用print时,函数才真正创建。
模板生成类
#include<iostream>
#include<string>
using namespace std;
template<typename T,int N>
class Array
{
private:
T m_Array[N];
public:
int getsize()const { return N ; }
};
int main()
{
Array<int,5> array;//创建一个Array类,所有的T替换成int,所有的N替换成5
cin.get();
}
如果不使用模板,那么在栈上创建的数组在编译期间就必须知道它的大小,而使用模板在调用时才会创建。
内存分配
#include<iostream>
#include<string>
using namespace std;
struct Vector
{
int x, y, z;
Vector()
:x(10),y(11),z(12) {}
};
int main()
{
//栈上分配
int value = 5;
int array[5] = { 1,2,3,4,5 };
Vector v1;
//堆上分配
int* hvalue = new int(5);
int* harray = new int[5];
harray[0] = 1;
harray[1] = 2;
harray[2] = 3;
harray[3] = 4;
harray[4] = 5;
Vector* hv1 = new Vector();
cin.get();
delete hvalue, hv1;
delete[] harray;
}
第一个部分是在栈上分配内存,第二个部分是在堆上分配内存(用关键字 new ),打上断点进行调试,在内存中可以看见value、array、v1 的位置其实挨得很近,他们之间的字节( cc )是在debug模式运行下添加的安全守卫,确保变量溢出时不会影响到其他变量。
在栈上分配内存时,实际上是栈顶部的指针移动变量所需字节大小, 我用的VS2022,变量是从低地址向高地址分配的,其他版本可能不同。
在堆上分配则上面这些特征。new 实际上是调用了 malloc 。简单来说,当启动程序时我们会得到一定数量的物理ram;程序会维护一个叫空闲列表的东西,用于追踪那些内存块是空闲的,位置在哪以及被分配的情况。
在代码生成的汇编中我们可以看出,栈上分配只是一条简单的cpu指令,堆上分配则多出了很多语句,所以栈上分配的速度要快许多,实际上,不是必须在堆上分配(变量需要超出函数作用域的寿命,或者要分配的内存很大),采用栈上分配是最好的。