c++内存管理和模板

打印 上一主题 下一主题

主题 556|帖子 556|积分 1668

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不会返回空,若申请空间失败了,如果用户有实行相应措施,则它会调用相应措施,继续申请,如果没有,它会抛非常
  1. const int N=100;
  2. class stack
  3. {
  4.         stack(int capacity=4)
  5.         {
  6.                 _capacity=capacity;
  7.                 _size=0;
  8.                 arr=new int[_capacity];
  9.         }
  10.         ~stack()
  11.         {
  12.                 free(arr);
  13.                 _capacity=_size=0;
  14.         }
  15. private:
  16.         int* arr;
  17.         int _capacity;
  18.         int _size;
  19. };
  20. stack* func(int n=10)
  21. {
  22.         stack* pst=new stack;
  23.         return pst;
  24. }
  25. int main()
  26. {
  27.         int capacity=N;
  28.         int* arr1=new int[capacity];//开辟数组 new datatype[]的方括号里面是完成对n个对象的调用申请
  29.         delete[] arr1;
  30.         //
  31.         stack* pst=func(N);
  32.         delete pst;//析构函数先把stack里的arr释放掉,delete再释放掉pst指向的空间
  33. }
复制代码
如果你想捕获非常,可以用以下代码
  1. int main()
  2. {
  3.         try
  4.         {
  5.                 char* p=new char[0x7fffffff];//可更换
  6.                 //即使是一个函数,也可以在异常处中断,跳到catch
  7.         }
  8.         catch(const exception& e)
  9.         {
  10.                 cout<<e.what()<<endl;
  11.         }
  12.         return 0;
  13. }
复制代码
不匹配题目

有时候我们会malloc,new,free,delete,new[ ],delete[ ]混着用,这是会出题目的
  1. class V
  2. {
  3. public:
  4.         stack(int a=1)
  5.         :_a(a)
  6.         {}
  7.         //但一旦我加上析构函数,这里就会报错了
  8. private:
  9.         int _a;
  10. };
  11. int main()
  12. {
  13.         stack* pst=new stack;
  14.         free(pst);//会报错,因为内存泄漏
  15.         delete(pst);//正常
  16.         A* pA=new A[10];
  17.         //free(pA);//报错
  18.         //delete pA;//报错
  19.         delete[]pA;
  20. }
复制代码
为什么有了析构函数就会报错呢?由于在new 出n个空间的时候,编译器会在空间前面加四个字节,用来存储对象的个数,但是只返回cur的位置

我们在申请内存的时候不能只申请一部门,如果上面用free大概delete的话,会从cur位置开始释放,而不是从最开始位置开始释放,只有delete[ ]会往前偏移四个字节,至于为什么有析构函数编译器就会报错的题目,编译器在没有析构函数的时候会主动去优化,而有析构函数的时候不得不实行,然后就报错了
定位new

构造函数不能显式调用,析构函数可以显式调用,如果我们一定要调用构造函数的话,可以用下面这种方法
  1. class stack
  2. {
  3. public:
  4.         stack(int capacity=4)
  5.         {
  6.                 _capacity=capacity;
  7.                 _size=0;
  8.                 arr=new int[_capacity];
  9.         }
  10. private:
  11.         int* arr;
  12.         int _size;
  13.         int _capacity;
  14. };
  15. int main()
  16. {
  17.         stack* pst1=new stack;
  18.         pst1->stack();//不允许
  19.         new(pst1)stack();//定位new
  20.         return 0;
  21. }
复制代码
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的时候每次都只能实现一种类型的交换,固然说我们用函数重载可以办理一部门的题目,但仍然存在着缺陷,由于他们内部的逻辑都是一样的,只有类型不一样,但又不得不写,就会显得代码很繁琐
  1. void swap(int& a1,int& a2)
  2. {
  3.         int tmp=a1;
  4.         a1=a2;
  5.         a2=tmp;
  6. }
  7. void swap(char& a1,char& a2)
  8. {
  9.         char tmp=a1;
  10.         a1=a2;
  11.         a2=tmp;
  12. }
  13. void swap(double& a1,double& a2)
  14. {
  15.         double tmp=a1;
  16.         a1=a2;
  17.         a2=tmp;
  18. }
复制代码
如果我们有函数模板就可以办理这个题目
函数模板

  1. template<class T>
  2. void swap(T& a1,T& a2)
  3. {
  4.         T tmp=a1;
  5.         a1=a2;
  6.         a2=tmp;
  7. }
  8. int main()
  9. {
  10.         int a1=1,a2=2;
  11.         double b1=1.0,b2=2.0;
  12.         swap(a1,a2);//隐式实例化
  13.         swap(b1,b2);
  14. }
复制代码
我们去用不同类型调试的时候会发现它都进入了同一个函数代码,但实际上它进去的是编译器通过T模板实例化后的函数,以是他们调用的是不一样的函数,如果你进入函数反汇编去看,你会发现这两个swap函数的汇编代码有一句不一样,一个是swap< int >(地点),另一个是swap< double >(地点)
类模板

我们在写一些类的时候,比如说栈,有时候我们栈只能写一个int类型,然后拷贝一份再写一个double类型,但内部的逻辑都是一样的,会很贫苦,以是类也引进了类模板
  1. template<class T>
  2. class stack
  3. {
  4. public:
  5.         stack(int capacity=4)
  6.         :_size(0)
  7.         ,_capacity(capacity)
  8.         {
  9.                 arr=new T[_capacity];
  10.         }
  11.         ~stack()
  12.         {
  13.                 delete[] arr;
  14.                 _size=_capacity=0;
  15.         }
  16. private:
  17.         T* arr;
  18.         int _size;
  19.         int _capacity;
  20. };
  21. //我们在使用的时候在类的后面要加入模板类型
  22. int main()
  23. {
  24.         stack<int> st1;
  25.         stack<double> st2;//显式实例化
  26.         return 0;
  27. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

汕尾海湾

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表