C++之new 和 delete

new 和 delete要成对使用,且要采取相同形式


使用new时,会发生2件事,1.内存被分配出来;2.针对此内存会有一个(更多)构造函数被调用;

使用delete,发生2件事,1.针对此内存的析构函数被调用;2.内存被释放;

举例:

std::string * stringPtr1 = new std::string;

std::string * stringPtr2 = new std::string[100];


delete stringPtr1;

delete [] stringPtr2;


开发人员为了研究学习他们的软件使用内存的行为特征,然后修改分配和归还工作,以求获得其所建置的系统的最佳效率

定制new和delete:主角是operator new和 operator delete,配角是new-handler

了解new-handler的行为:

首先介绍客户指定的错误处理函数的使用方法:调用set_new_handler

namespace std{

typedef void (*new_handler) ();------new_handler被定义为函数指针

        new_handler set_new_handler(new_handler p) throw(); 返回值是一个指针,指向set_new_handler 被调用前正在执行的那个new-handler函数

}

如何为每一个class 设计专属的new-handlers?需要为class提供自己的set_new_handler和operator new即可。

举例:

class Widget{

public:

static std::new_handlerset_new_handler(std::new_handler p) throw();

static void* operator new(std::size_t size) throw(std::bad_alloc);

private:

static std::new_handlercurrentHandler;

}

std::new_handler Widget::currentHandler = 0; //Static 成员必须在class 定义式之外定义,除非他们是const且是整数型。

std::new_handler Widget::set_new_handler(std::new_handler p) throw()//标准的set_new_handler

{

std::new_handler oldHandler = currentHandler;

currentHandler = p;

return oldHandler;

}


class NewHandlerHolder{

public:

explicit NewHandlerHolder(std::new_handler nh) : handler(nh){}//防止隐式转换

~NewHandlerHolder(){std::set_new_handler(handler);} //恢复new_handler

private:

std::new_handler  handler;

NewHandlerHolder(const NewHandlerHolder&);  //拒绝使用复制和赋值构造

NewHandlerHolder& operator=(const NewHandlerHolder&);

}


void * Widget::operator new(std::size_t size) throw(std::bad_alloc)

{

NewHandlerHolder h(std::set_new_hanlder(currentHandler));//保存全局的handler

return ::operator new(size);

}

//采用模板方式建立一个复用的baseclass,采用的方式是CRTP

请记住:

set_new_handler 允许客户指定一个函数,在内存分配无法获得满足时被调用

Nothrow new是一个颇为局限的工具,因为它只是用内存分配;后继的构造函数调用还是可能抛出异常

了解何时在“全局性的”或“class 专属的”基础上合理体寒缺省的new和delete。

1. 为了检测运用错误

2. 为了收集动态分配内存之使用统计信息

3. 为了增加分配和归还的速度

4.为了降低缺省内存管理器带来的空间额外开销

5.为了弥补缺省分配器重的非最佳齐位

6.为了将相关对象成簇集中

7.为了获得非传统的行为

举例:对heap 运用错误进行调试的定制new和delete开发

http://blog.sina.com.cn/s/blog_65e729050100m7uw.html

编写new和delete时需要固守常规

原则:实现一致性operator new必得返回正确的值;内存不足时必得调用new-handling 函数;

           必须有对付零内存需求的准备;避免不慎掩盖正常形式的new

举例:满足前三条

void* operator new(std::size_t size)

{

using namespace std;

if(0 == size){

size = 1;

}

while(true){

void* p = ::operator new(size);

if(null != p) return p;

new_handler globalHandler = set_new_handler(0);

set_new_handler(globalHandler);

if(globalHandler) (*globalHandler)();

else throw std::bad_alloc();

}

}

如果涉及到派生类继承要如何处理呢?

calss Base{

public:

static void* operator new(std::size_t size) throw(std::bad_alloc);

static void  operator delete(void* rawMemory,std::size_t size) throw();

};

void* Base :: operator new(std::size_t size) throw(std::bad_alloc)

{

if(size != sizeof(base))

return ::operator new(size);

}

void Base::operator delete(void* rawMemory,std::size_t size) throw()

{

if(rawMemory == 0)return ;

if(size != sizeof(Base)){

::operator delete(rawMemory);

return ;

//归还所指的内存

return ;

}

//placement new 和placement delete

placement new的定义如下:

void * operator new(std::size_t, void* pMemory) throw();

步骤一:Widget* pw = new Widget;共有两个函数被调用,1是分配内训的operator new;一个是Widget的默认构造函数

步骤二:

class Widget{

public;

static void* operator new(std::size_t size,std::ostream& logStream)throw (std::bad_alloc);

static void operator  delete(void* pMemory,sdd::size_t size)throw();

}

如果内存分配成功,但是在构造函数中失败的话,运行期系统会做内存的处理,它会找寻域operator new

类似的operator delete,否则就会找不到对应的释放参数 而导致内存泄露。

不要掩盖正常的operator, 一定要成对出现。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值