new和delete的使用

1、操作符与表达式

#include <iostream>

using namespace std;

class A
{
public:
    A():a(100),b(200)
    {
        std::cout << "constructor " << std::endl;
    }
    ~A()
    {
        std::cout << "destructor " << std::endl;
    }
    void f()
    {
        std::cout << a << "   " << b << std::endl;
    }
private:
    int    a;
    double b;
};

int main()
{
    void* p = operator new(sizeof(A)); //<new操作符>,只负责分配内存
    p = new (p)A;                      //<定位new> 在内存块上调用类的构造函数
    static_cast<A*>(p)->f();
    static_cast<A*>(p)->~A();          //定位new的逆操作,调用析构函数 内存未释放
    operator delete(p);                //<delete操作符>,只负责释放内存

    /*
    A* p1 = new A;  //<new表达式> 这和上面的效果一样,申请一块内存,然后执行构造函数
    p1->f();
    delete p1;      //<delete表达式> 这和上面的效果一样,调用析构函数 然后释放内存
    */

    system("pause");
    return 0;
}
2、重载的new/delete

void operator delete(void* p, int t)这个函数也是默认的参数列表,但是只有在void operator delete(void* p)没有提供的时候作为默认;对于多参数重载版本,在new的时候可以直接使用,但是在delete的时候就无法直接调用,直接delete(20) p2使用是非法的。

多参数delete只在相同版本的new在使用的时候,构造函数抛出异常时,并且异常被捕捉的情况下,由系统自动调用。

#include <iostream>  
  
using namespace std;  
  
class A  
{  
public:
    A(){ std::cout << "A::constructor " << std::endl; }
    ~A(){ std::cout << "A::destructor " << std::endl; }
    A(int e)
    {
        std::cout << "A::constructor throw exception" << std::endl; 
        throw int(0);
    }

    void* operator new(size_t size) //默认参数列表new 
    {
        std::cout << "void A::operator new(size_t size)" << std::endl;
        return ::operator new(size);
    }
    void operator delete(void* p)//默认参数列表delete
    {
        std::cout << "void A::operator delete(void* p)" << std::endl;
        return ::operator delete(p);
    }

    //构造的new/delete
    void* operator new(size_t size, int t) //多参数列表new
    {
        std::cout << "void A::operator new(size_t size, int t) : \t" << t << std::endl;
        return ::operator new(size);
    }
    void operator delete(void* p, int t)//多参数列表delete
    {
        std::cout << "void A::operator delete(void* p, int t) : \t" << t << std::endl;
        return ::operator delete(p);
    }
};  

class B
{
public:
    B(){ std::cout << "B constructor" << std::endl; }
    ~B(){ std::cout << "B destructor" << std::endl; }
};

class C: public A
{
public:
    C(){}
    C(int){ throw int(0);}
    void* operator new(size_t size) //默认参数列表new 
    {
        std::cout << "void C::operator new(size_t size)" << std::endl;
        return ::operator new(size);
    }
    void operator delete(void* p)//默认参数列表delete
    {
        std::cout << "void C::operator delete(void* p)" << std::endl;
        return ::operator delete(p);
    }
};

//全局new/delete
void* operator new(size_t size)
{
    std::cout << "void* global::operator new(size_t size)" << std::endl;
    return malloc(size);
}
void operator delete(void* p)
{
    std::cout << "void global::operator delete(void* p)" << std::endl;
    free(p);
}

int main()  
{  
    //普通重载的new/delete
    std::cout << "=============================================" << std::endl;
    A* p1 = new A; //调用默认参数表的new
    delete p1;     //调用默认参数表的delete

    //多参数重载的new/delete
    std::cout << "=============================================" << std::endl;
    try
    {
        A* p2 = new(10) A(0); //调用带多参数的new,使用抛出异常的构造函数构造对象
        delete p2; //异常已经跑出,这里不会被调用
    }
    catch (int)
    {
        //在这里捕获了异常,那么使用的delete释放资源(就是和new匹配的delete{ void operator delete(void* p, int t) })
    }

    //全局重载的new/delete
    std::cout << "=============================================" << std::endl;
    B* pb = new B;
    delete pb;

    std::cout << "=============================================" << std::endl;
    try
    {

        A* c = new C;
        delete c;   //正常释放调用的是基类的delete,原因基类的析构不是virtual的,将析构改成virtual就正常了
        std::cout << "=============================================" << std::endl;
        c = new C(10);
    }
    catch(...)
    {
        //抛出异常调用的是派生类的delete释放资源
    }

    system("pause");  
    return 0;  
}  





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值