new和delete
Tmp* p=new Tmp();------new operator(不可重载)
申请内存(调用operator new)可以重载
调用构造
delete p ;-----delete operator(不可重载)
调用析构
内存释放(operator delete)可以重载
void* operator new(size_t size)重载函数
{
cout<<"void* operator new(size_t size)"<<endl;
void* p=malloc(size);
return p;
}
void operator delete(void* p)
{
cout<<"void operator delete(void* p)"<<endl;
free(p);
}
堆上的资源属于是外部资源
申请/释放外部资源————用户态没有权限,内核态
有权限
堆上的内存申请和释放的过程需要内核态完成————从用户态切换到内核态
系统调用:cout,printf,cin,scanf(调用外部资源的都得进行系统调用)
内存池
:用户态自己维护的一大段内存
重载new和delete相当于留下了一个可修改的端口,可以指定内存的申请和释放的内存池
c++自带的内存池:_Alloc
MFC编译器:new和delete进行全局重载时检测内存泄露的工具
有一个全局链表,当new时,将地址加入到链表,delete时将地址从链表中删除,,程序执行完了后,打印链表中的数据,如果有则内存泄漏
模板
重载
:函数名相同,参数列表不同(静多态
,编译时期的多态,早绑定)
模板
不可以直接运行,模板会在编译时期根据使用情况生成对应的函数指令
模板
不编译,模板生成的函数指令会编译,模板中的语法错误会在生成对应的指令时候被编译错误
函数模板有类型自推的能力,使用函数模板可以不用传模板类型的参数eg:compare(10,20),int 可不用写
template<typename T>
bool compare(T a,T b)
{
return a>b;
}
int main()
{
compare(10,20);
if(compare("aaa","bbb"))传入const char*会直接比较地址
{
cout<<"aaa">"bbb"<<endl;
}
}
template<typename T>
void sort(T* arr,int len)
{
if(srr==NULL)return;
for(int i=0;i<len-1;++i)
{
for(int j=i+1;j<len-i-1;++j)
{
T temp=arr[i];
if(arr[j]<arr[i])
{
arr[i]=arr[j];
arr[j]=tmp;
}
}
}
模板的完全泛化,部分特例化,完全特化
template<class T>完全泛化,只要是类型就可以根据该模板写出对应的函数
void fun(T a)
{
T x,y;
cout<<"T type"<<typeid(T).name()<<endl;
cout<<"a type"<<typeid(a).name()<<endl;
}
template<class T>
void fun(T* a)部分特例化,只要是指针就可以
{
T x,y;
cout<<"T type:"<<typeid(T).name()<<endl查看T的类型
cout<<"a type:"<<typeid(a).name()<<endl查看T的类型
}
template<>完全特化,必须为char*
void fun<char*>(char* a)
{
}
类模板
不编译,会在编译时期根据使用方式,生成对应的类代码(指令)
类模板中在main函数中没有使用到的成员方法不实现是不会报错
的,只有在main中调用才会报错
类模板使用的时候必须加上模板类型的参数,无法自己推导类型函数
类模板的成员方法只能在头文件中实现或者在使用到的cpp文件中实现,不能分开实现在.h和另一个.cpp(除了写main函数的.cpp文件)
因为类模板在编译时期将使用到的成员方法生成对应的指令,编译器只针对单文件,如果将类模板的成员方法实现在了其他文件,编译时期使用到的该方法的文件不可见,就无法生成对应的指令,————无法解析的外部符号
在另一个文件中,因为没有使用到它的地方所以不编译,因此链接时也无法找到
template<class T,int N>
class Stack
{
T data[N];
public:
void push(const T&x);
}
int main()
{
Stack<int,100> is;
Stack<int,10> ist;
}
template<typename T>
class Arr
{
private:
T* arr;
int _len;
int _val_len;
public:
Arr()
{
cout<<"Arr()"<<endl;
}
void push_back(const T&val);
};
int main()
{
Arr<int> arr;必须加类型,不会自己推导
}
类模板的特例化
template<>
class Arr<const char*>
{
private:
const char** arr;
int _len;
int _val_len;
const char** arr;
public:
Arr()
{
cout<<"Arr<const char*>"<<endl;
}
void push_back(const char*val);
友元函数模板
template<typename TT>
friend ostream& operator<<(ostream& out,Arr<TT>& src);
};
模板里的成员方法在类外实现时,多了个T,因为Arr是模板,加上T才是类名
template<typedef T>
void Arr<T>::push_back(const T&val);
template<typedef T>
ostream& operator<<(ostream& out,Arr<T>& src)
{
for(int i=0;i<src.size();++i)
{
out<<src[i]<<" ";
}
cout<<endl;
}
int main()
{
Arr<const char*> arr;
}