new和delete心得

最近研究运算符重载,突然了解到new和delete也是C++运算符(惭愧),以前只知道是关键字.偶有一点心得记于博客.

首先,new和malloc一样,都是C++申请动态内存的操作,但是new除了申请内存,还要对内存进行初始化,就是我们所说的调用构造函数.

其次,new申请内存失败的时候,会抛出std::bad_alloc异常, 而malloc则会返回空指针,但是如果使用new(std::nothrow)T(X1,X2...)形式,则不会抛出异常,申请失败则会返回空指针

再次,new底层的操作其实是调用malloc,在malloc返回空的时候,抛出异常

最后,来说说new的原理,

 int *i= new int(3);

上面这个表达式很简单,就是new一块int型的内存,然而这里面却包含2步操作:

1.首先,调用全局的operator new(size_t size)申请一块长度为sizeof(int)的内存,

2.然后,对这块内存进行初始化,就是调用int的构造函数,把这块内存值初始化为3

根据以上2步,其实该表达式完全可以用以下表达式进行表达:

int* i = (int*)operator new(sizeof(int));

new(i)int(3); 

?,充满了疑问,是不是没见过上面2种形式的表达式,其实很简单,上面2种表达式就是c++标准库的operator new的2种形式,第一种格式为void* operator new (size_t size), 第2种形式为void* operator new(size_t size, void* _Where),这2个是函数,可以直接进行调用,第一个表达式就是申请内存,第二个表达式就是返回申请到内存的指针,调用构造函数进行初始化

T*i = new T[N];

上述表达式是new[]的形式,同new也包含2步操作,

1.调用operator new(size_t size)进行申请内存的操作,但是这里的size长度不一定是sizeof(T)*N,但是T是基本类型(如int)时候,size的值为sizeof(int)*N,但是如果T是自定义长度就>sizeof(T)*N,我在VS2008测试,得出size的长度为sizeof(T)*N+4.我猜测是C++需要一部分内存对该数组进行管理

2.调用T的构造函数T()对数组里的每个对象都进行初始化

但是该表达式却不能等价于以下表达式:

T* i = (T*)operator new(sizeof(T)*N);

new(i)T; 

首先这里申请的内存大小为sizeof(T)*N(因为自己管理该内存,不需要C++去管理,所以N个数组所占的内存就是这么多),其次new(i)T只是对数组的第一个对象进行初始化,可以使用

for (int j = 0; j < N; j++)

{

new(i+j*sizeof(T))T;

}

分别进行初始化

 

下面说说operator new的重载,

operator new 重载为成员函数的格式为 <static>void* operator new(size_t size,X1,X2...);其中要求第一个参数必须是size_t, 返回值必须是void*类型.而且static可带可不带,因为不带static也会隐式的转为静态函数,因为operator new是在构造函数前进行操作的如下例

class TestClass
{
public:
    TestClass(void);
    ~TestClass(void);

public:

   /*friend*/ new_handler set_new_handler(new_handler p);

    void* operator new (size_t size)....................1
    {
        return malloc(size);
    }

 

    void* operator new (size_t size, int j, int v)...........................2
    {
        return malloc(size);
    }

 

    void* operator new (size_t size, void* p)........................3
    {
        return p;
    }

    void* operator new[] (size_t size)
    {
        return malloc(size);
    }

    void operator delete (void* p)
    {
        free(p);
    }

    void operator delete[] (void* p)
    {
        free(p);
    }
};

调用重载new的格式为new(X1,X2...)T,如上类,当你使用TestClass *p = new TestClass;将会先调用1,在调用构造函数,使用TestClass *p = new(3,5) TestClass;将会先调用2在调用构造函数,如果使用void* p = operator new(sizeof(TestClass))将会调用C++标准库的operator new(size_t size),若要使用重载成员则为

void* p = TestClass::operator new(sizeof(TestClass)),同理new[]重载形式为 <static>void* operator new[](size_t size,X1,X2...);

delete重载形式为<static>void operator delete(void*p,X1,X2...);返回值必须为void,第一个参数为void*

delete[]重载形式为<static>void operator delete[](void*p,X1,X2...);返回值必须为void,第一个参数为void*

如果重载为友元函数,其实就是全局函数,则格式不变只是在前面添加一个friend 如friend void* operator new(size_t size,X1,X2...);但是有个比较特殊的是

void* operator new(size_t  size, void* p )不能重载为友元即全局的

 

最后,如果你重载了new函数,也要重载对应的 delete

其实new和delete还有很多东西, 如 new在抛异常前线调用的错误处理函数,new_handler set_new_handler(new_handler p);也是可以重载的(如上类),new的异常处理等等,今天没时间写了,有心的人可以自己找点资料,这里只做简单的介绍

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值