内存管理
5. new和delete的实现原理
5.1 内置类型
如果申请的是内置类型的空间,new和malloc,delete和free基本类似,不同的地方是:
new/delete申请和释放的是单个元素的空间,new[]和delete[]申请的是连续空间,而且new在申请空间失败时会抛异常,malloc会返回NULL。
5.2 自定义类型
new的原理
new是一个操作符,malloc是一个函数
1. 调用operator new函数申请空间
2. 在申请的空间上执行构造函数,完成对象的构造
delete的原理
1. 在空间上执行析构函数,完成对象中资源的清理工作
2. 调用operator delete函数释放对象的空间
new T[N]的原理
1. 调用operator new[]函数 -》封装malloc ,在operator new[]中实际调用operator new函数完成N个对象空间的申请
2. 在申请的空间上执行N次构造函数
delete[]的原理
1. 在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理
2. 调用operator delete[]释放空间,实际在operator delete[]中调用operator delete来释放空间
new/delete 和 malloc/free不要交叉使用,否则结果不是很确定,可能会出大问题!!!
new/malloc系列,与底层实现机制相关,不匹配使用,可能有问题,所以最好不要不匹配使用
例:
A* p8 = new A;
free(p8);//少调用析构函数
Stack* pst = new Stack;
free(pst);//少调用析构函数,如果这个析构函数原本是要对某些对象的资源
//进行清理,这样就导致了内存泄漏
6.定位new
对一块已经开辟的空间进行初始化
使用格式:
new (place_address) type或者new (place_address) type(initializer-list)
place_address必须是一个指针,initializer-list是类型的初始化列表
int main()
{
A* p1 = (A*)malloc(sizeof(A));
if(p1 == nullptr)
{
perror("malloc fail");
}
new(p1)A(1);
}
泛型编程 --- 模板
函数模板
函数模板格式
template<typename T1, typename T2,......,typename Tn>
返回值类型 函数名(参数列表){}
注意:typename是用来定义模板参数关键字,也可以使用class(切记:不能使用struct代替class)
函数模板概念
函数模板代表了一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生函数的特定类型版本。将这个工作交给编译器去做了
模板参数的匹配原则
1. 一个非模板函数可以和一个同名的函数模板同时存在,而且该函数模板还可以被实例化为这个非模板函数
2. 对于非模板函数和同名函数模板,如果其他条件都相同,在调动时会优先调用非模板函数而不会从该模板产生出一个实例。如果模板可以产生一个具有更好匹配的函数, 那么将选择模板
例:
template<class T>
void Swap(T& x, T& y)
{
T tmp = x;
x = y;
y = tmp;
}
显示实例化:
template<class T1,class T2>
T1 Add(T1 x, T2 y)
{
return x + y;
}
//显示实例化
cout << <int>Add(a,b) << endl;
cout << <double>Add(a,b) << endl;
//隐式实例化,实参传递给形参,自动推演模板类型
cout << Add(a,b) << endl;
cout << Add(a,b) << endl;
3.类模板
typedef不能允许两个不同的类型同时出现
类化模板只能显示实例化
- 它是类型无关的,因此具有很高的可复用性
- 它运行时检查数据类型,保证了类型安全
- 它是平台无关的,可移植性
template<class T1, class T2, ..., class Tn>
class 类模板名
{
// 类内成员定义
};