c++ new delete知识总结

一、C++的动态对象创建

当创建一个C++对象时,会发生两件事:
(1)为对象分配内存
(2)调用构造函数来初始化那个内存

然而,为对象分配内存可以用以下几种方式或在可选择的时间发生:
(1)在静态存储区域,存储空间在程序开始之前就可以分配。这个存储空间在整个运行期间都存在。
(2)无论何时到达一个特殊的执行点(左大括号)时,存储单元都可以在栈上被创建。出了执行点(右大括号),这个存储单元自动被释放。这些栈分配运算内置于处理器的指令集中,非常有效。但是,在写程序的时候,必须知道需要多少个存储单元,以便编译器知道生成正确的指令。
(3)存储单元也可以从一块称为堆的地方分配。这被称为动态内存分配。在运行时调用程序分配这些内存。这就意味着在任何时候可以分配内存以及分配多少内存,当然也需要负责决定何时释放内存。

二、C++的new 和 delete

C++中的解决方法是把创建一个对象所需的所有动作都结合在一个称为new的运算符里。我们当用new创建一个对象时,它就在堆里为对象分配内存并为这块内存调用构造函数。我们可以为类使用任何可用的构造函数,如果构造函数没有参数,可以写没有构造函数参数表的new表达式。

new表达式的反面是delete表达式。delete表达式首先调用析构函数,然后释放内存。如果正在删除的对象的指针是0,将不发生任何事情。为此,我们经常建议在删除指针后立即把指针赋值为0以免对它删除两次,从而产生某些问题。

#include <iostream>

using namespace std;

class B{
public:
     B(){
        cout<<"class b is created"<<endl;
    }
    ~B(){
        cout<<"class b is deleted"<<endl;
    }

};

int main(){

    B *a=new B;

    delete a;
    cout<<"-----------------"<<endl;

    B *b=new B[3];

    //空的方括号告诉编译器产生代码,该代码的任务是将从数组创建时存放在某处的对象数量取回,并为数组的所有对象调用析构函数。
    delete []b;
}

最终打印结果为:
class b is created
class b is deleted
-----------------
class b is created
class b is created
class b is created
class b is deleted
class b is deleted
class b is deleted

三、重载局部new delete

重载的new必须有一个size_t参数(不管是局部new还是全局new,不管是new 还是new[])。这个参数由编译器产生并传递给我们,它是要分配内存的对象的长度。必须返回一个指向等于这个长度(或者大于这个长度)的对象的指针。我们首先需要明白的一点就是:operator new()的返回值是一个void*。它所做的是分配内存,而不是完成一个对象建立–直到构造函数调用了才完成对象的创建,它是编译器确保做的动作,不在我们的控制范围之内了,所以我们就没有必要考虑。

当在一个类内部重载new和delete的时候,我们称之为重载局部new delete。为一个类重载new和delete的时候,尽管不必显式的使用static,但是实际上仍是在创建static成员函数。它的语法也和重载任何其它运算符一样。当编译器看到使用new创建自己定义的类的对象时,它会选择相应版本的局部new delete函数去执行。

#include <iostream>

using namespace std;

class A{
public:
    static int count;

    A(){
    cout<<"class a is created"<<endl;
    }
    ~A(){
        cout<<"class a is deleted"<<endl;
    }

    //局部new重载
    /*注意:当执行A *a=new A时,会先调用这个局部new重载函数,然后调用了2次构造函数,但返回的对象的内存地址却是相同的一个,因此可以理解为只创建了一个对象,不知道为啥会调用2次构造函数。*/
    static void * operator new(size_t size){
        cout<<"jubu new is called"<<endl;
        count++;
        A *a=::new A;

        return a;
    }

    //局部delete重载
    static void operator delete(void *p){
        cout<<"jubu delete is called "<<p<<endl;
        count--;
        ::delete p;

    }

    //局部new[]重载
    static void * operator new[](size_t size){
        cout<<"jubu [] new is called"<<endl;

        return operator new(size);
    }

    //局部delete[]重载
    static void operator delete[](void *p){
        cout<<"jubu [] delete is called"<<endl;
        operator delete(p);
    }
};

int A::count=0;



int main(){
    A *a=new A;//调用局部重载new
    delete a;//调用局部重载delete
    cout<<"-----------------"<<endl;

    A *b=new A[3];//调用局部重载new[]
    delete []b;//调用局部重载delete[]
}
上述程序输出结果为:
jubu new is called
class a is created   
class a is created
class a is deleted
jubu delete is called 0x7111a0
-----------------
jubu [] new is called
jubu new is called
class a is created
class a is created
class a is created
class a is created
class a is deleted
class a is deleted
class a is deleted
jubu [] delete is called
jubu delete is called 0x7111a0

四、全局new delete重载

全局new delete重载,即相关的重载方法,写在和main方法同级的代码块中,针对整个系统有效,而上述局部new delete重载只是针对本类有效。

#include <iostream>

using namespace std;

class A{
public:
    static int count;

    A(){
        cout<<"class a is created"<<endl;
    }
    ~A(){
        cout<<"class a is deleted"<<endl;
    }

    //局部new重载
    static void * operator new(size_t size){
        cout<<"jubu new is called"<<endl;
        count++;
        A *a=::new A;

        return a;
    }

    //局部delete重载
    static void operator delete(void *p){
        cout<<"jubu delete is called "<<p<<endl;
        count--;
        ::delete p;

    }

    //局部new重载
    static void * operator new[](size_t size){
        cout<<"jubu [] new is called"<<endl;

        return operator new(size);
    }

    //局部delete重载
    static void operator delete[](void *p){
        cout<<"jubu [] delete is called"<<endl;
        operator delete(p);
    }
};

int A::count=0;

//全局new重载
void * operator new(size_t size){
    if(size==0){
        return 0;
    }
    void *p=malloc(size);
    cout<<"quanju new is called "<<p<<endl;
    return p;
}
//全局new[]重载
void * operator new[](size_t size){
    cout<<"quanju[] new is called "<<endl;
    return operator new(size);
}
//全局delete重载
void operator delete(void *p){
    cout<<"quanju delete is called "<<p<<endl;
    free(p);
}
//全局delete[]重载
void operator delete[](void *p){
    cout<<"quanju[] delete is called "<<p<<endl;
    operator delete(p);
}

int main(){
    int *x=new int(12);
    delete x;
    cout<<"----------"<<endl;

    int *p=new int[10];
    delete []p;
    cout<<"-----------------"<<endl;

    A *a=new A;
    delete a;
    cout<<"-----------------"<<endl;

    A *b=new A[3];
    delete []b;
}
上述程序执行结果为:
//int *x=new int(12);
//delete x;
quanju new is called 0x1e11a0
quanju delete is called 0x1e11a0
----------
//int *p=new int[10];
//delete []p;
quanju[] new is called
quanju new is called 0x1e11a0
quanju[] delete is called 0x1e11a0
quanju delete is called 0x1e11a0
-----------------
//A *a=new A;
//delete a;
jubu new is called
quanju new is called 0x1e11a0
class a is created
class a is created
class a is deleted
jubu delete is called 0x1e11a0
quanju delete is called 0x1e11a0
-----------------
//A *a=new A[3];
//delete []a;
jubu [] new is called
jubu new is called
quanju new is called 0x1e11a0
class a is created
class a is created
class a is created
class a is created
class a is deleted
class a is deleted
class a is deleted
jubu [] delete is called
jubu delete is called 0x1e11a0
quanju delete is called 0x1e11a0

五、总结

当局部、全局new delete都被重载后,其和构造方法、析构方法的调用是有顺序的,具体如下图所示:
这里写图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值