ToB企服应用市场:ToB评测及商务社交产业平台
标题:
c++内存管理和模板
[打印本页]
作者:
汕尾海湾
时间:
2024-9-4 12:32
标题:
c++内存管理和模板
C语言malloc calloc和realloc的弊端
C语言的这三个函数对于内置类型的处理是还可以的,但是对自界说类型就无法处理了,由于c++自界说类型在初始化的时候是主动调用构造函数的,而C语言的这三个函数是无法初始化内置类型的,于是我们下面要先容new和delete两个关键字,以是在用new创造空间时,会主动调用构造函数,在用delete释放空间时,会主动调用析构函数
new和delete
new和delete的用法
operator new和operator delete实际上是通过malloc和free开启空间,只是new在申请新空间的时候,对于自界说类型会调用默认构造函数,delete在释放自界说类型的空间的时候,会先调用自界说类型的析构函数,然后再free掉这块空间
此外,new和malloc不一样,malloc失败后会返回空,而new不会返回空,若申请空间失败了,如果用户有实行相应措施,则它会调用相应措施,继续申请,如果没有,它会抛非常
const int N=100;
class stack
{
stack(int capacity=4)
{
_capacity=capacity;
_size=0;
arr=new int[_capacity];
}
~stack()
{
free(arr);
_capacity=_size=0;
}
private:
int* arr;
int _capacity;
int _size;
};
stack* func(int n=10)
{
stack* pst=new stack;
return pst;
}
int main()
{
int capacity=N;
int* arr1=new int[capacity];//开辟数组 new datatype[]的方括号里面是完成对n个对象的调用申请
delete[] arr1;
//
stack* pst=func(N);
delete pst;//析构函数先把stack里的arr释放掉,delete再释放掉pst指向的空间
}
复制代码
如果你想捕获非常,可以用以下代码
int main()
{
try
{
char* p=new char[0x7fffffff];//可更换
//即使是一个函数,也可以在异常处中断,跳到catch
}
catch(const exception& e)
{
cout<<e.what()<<endl;
}
return 0;
}
复制代码
不匹配题目
有时候我们会malloc,new,free,delete,new[ ],delete[ ]混着用,这是会出题目的
class V
{
public:
stack(int a=1)
:_a(a)
{}
//但一旦我加上析构函数,这里就会报错了
private:
int _a;
};
int main()
{
stack* pst=new stack;
free(pst);//会报错,因为内存泄漏
delete(pst);//正常
A* pA=new A[10];
//free(pA);//报错
//delete pA;//报错
delete[]pA;
}
复制代码
为什么有了析构函数就会报错呢?由于在new 出n个空间的时候,编译器会在空间前面加四个字节,用来存储对象的个数,但是只返回cur的位置
我们在申请内存的时候不能只申请一部门,如果上面用free大概delete的话,会从cur位置开始释放,而不是从最开始位置开始释放,只有delete[ ]会往前偏移四个字节,至于为什么有析构函数编译器就会报错的题目,编译器在没有析构函数的时候会主动去优化,而有析构函数的时候不得不实行,然后就报错了
定位new
构造函数不能显式调用,析构函数可以显式调用,如果我们一定要调用构造函数的话,可以用下面这种方法
class stack
{
public:
stack(int capacity=4)
{
_capacity=capacity;
_size=0;
arr=new int[_capacity];
}
private:
int* arr;
int _size;
int _capacity;
};
int main()
{
stack* pst1=new stack;
pst1->stack();//不允许
new(pst1)stack();//定位new
return 0;
}
复制代码
malloc,new,free,delete的区别
1.malloc和free是函数,而new和delete是操作符
2.malloc申请的空间不会初始化,而new开发的空间会初始化
3.malloc申请空间的时候,必要手动计算申请空间,而new只必要在new后面加上类型,若有多个,则可以在类型后面加上[数目]
4.malloc返回的类型是void*,必要强转,而new不必要强转,由于new后面跟着的就是空间类型
5.malloc失败后会返回空,而new失败后会报错,必要捕获非常
6.malloc和free在使用的时候只会开发空间,而new在使用的时候会先开空间,再调用构造函数,而delete会先调用析构函数,再去释放空间
泛型编程
泛型编程就是针对广泛的类型去编程,我们在实现交换函数swap的时候每次都只能实现一种类型的交换,固然说我们用函数重载可以办理一部门的题目,但仍然存在着缺陷,由于他们内部的逻辑都是一样的,只有类型不一样,但又不得不写,就会显得代码很繁琐
void swap(int& a1,int& a2)
{
int tmp=a1;
a1=a2;
a2=tmp;
}
void swap(char& a1,char& a2)
{
char tmp=a1;
a1=a2;
a2=tmp;
}
void swap(double& a1,double& a2)
{
double tmp=a1;
a1=a2;
a2=tmp;
}
复制代码
如果我们有函数模板就可以办理这个题目
函数模板
template<class T>
void swap(T& a1,T& a2)
{
T tmp=a1;
a1=a2;
a2=tmp;
}
int main()
{
int a1=1,a2=2;
double b1=1.0,b2=2.0;
swap(a1,a2);//隐式实例化
swap(b1,b2);
}
复制代码
我们去用不同类型调试的时候会发现它都进入了同一个函数代码,但实际上它进去的是编译器通过T模板实例化后的函数,以是他们调用的是不一样的函数,如果你进入函数反汇编去看,你会发现这两个swap函数的汇编代码有一句不一样,一个是swap< int >(地点),另一个是swap< double >(地点)
类模板
我们在写一些类的时候,比如说栈,有时候我们栈只能写一个int类型,然后拷贝一份再写一个double类型,但内部的逻辑都是一样的,会很贫苦,以是类也引进了类模板
template<class T>
class stack
{
public:
stack(int capacity=4)
:_size(0)
,_capacity(capacity)
{
arr=new T[_capacity];
}
~stack()
{
delete[] arr;
_size=_capacity=0;
}
private:
T* arr;
int _size;
int _capacity;
};
//我们在使用的时候在类的后面要加入模板类型
int main()
{
stack<int> st1;
stack<double> st2;//显式实例化
return 0;
}
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/)
Powered by Discuz! X3.4