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企服之家,中国第一个企服评测及商务社交产业平台。 |