汕尾海湾 发表于 2024-9-4 12:32:50

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;
        }
        ~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;//开辟数组 new datatype[]的方括号里面是完成对n个对象的调用申请
        delete[] arr1;
        //
        stack* pst=func(N);
        delete pst;//析构函数先把stack里的arr释放掉,delete再释放掉pst指向的空间
}
如果你想捕获非常,可以用以下代码
int main()
{
        try
        {
                char* p=new char;//可更换
                //即使是一个函数,也可以在异常处中断,跳到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;
        //free(pA);//报错
        //delete pA;//报错
        delete[]pA;
}
为什么有了析构函数就会报错呢?由于在new 出n个空间的时候,编译器会在空间前面加四个字节,用来存储对象的个数,但是只返回cur的位置
https://i-blog.csdnimg.cn/direct/9dd199b718a74f0683ab79de6af34322.png
我们在申请内存的时候不能只申请一部门,如果上面用free大概delete的话,会从cur位置开始释放,而不是从最开始位置开始释放,只有delete[ ]会往前偏移四个字节,至于为什么有析构函数编译器就会报错的题目,编译器在没有析构函数的时候会主动去优化,而有析构函数的时候不得不实行,然后就报错了
定位new

构造函数不能显式调用,析构函数可以显式调用,如果我们一定要调用构造函数的话,可以用下面这种方法
class stack
{
public:
        stack(int capacity=4)
        {
                _capacity=capacity;
                _size=0;
                arr=new int;
        }
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;
        }
        ~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企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: c++内存管理和模板