C++之编写new和delete时需要固守常规(51)---《Effective C++》

本文探讨了C++中自定义new和delete运算符的重要性,详细解释了如何通过无限循环和new_handler来处理内存分配失败的情况,并提供了实现这些运算符的具体代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

条款51:编写new和delete时需固守常规

operator new中包含一个无限循环,而上述伪码明白表达出这个循环;“while(true)”就是那个无限循环,退出循环的唯一方法是:内存被成功分配或者new_hanlder从条款49的多个选择中选出一种进行选择,选择包括:让更多内存可用、安装另一个new_handler、卸载new_handler、抛出bad_alloc异常或者承认失败或者直接return,下面我们来看看operator new的伪码:

void* operator new(std::size_t size) throw(std::bad_alloc){
    using namespace std;
    if(size==0){
        size=1;
    }
    while(true){
        尝试分配size bytes;
        if(分配成功)
            return (一个指针,指向分配得来的内存);
        //分配失败
        new_handler globalHandler=set_new_handler(0);
        set_new_handler(globalHandler);

        if(globalHandler) (*globalHandler)();
        else throw std::bad_alloc();
    }
}

还有一个问题,许多人并没有意识到operator new成员函数会被derived classes继承,这回导致很多复杂的问题。因此我们需要重载机制,即将operator new和operator delete函数声明为virtual函数。

class Base{
public:
    static void* operator new(std::size_t size) throw(std::bad_alloc);
    ...
};
void Base::operator new(std::size_t size) throw(std::bad_alloc){
    if(size!=sizeof(Base))
        return ::operator new(size);//如果大小错误,令标准的operator new起而处理
    ...//否则在这里进行处理
class Derived:public Base
{...};
Derived *p=new Derived;//这里调用的是Base::operator new

上述代码我们可以看到operator new成员函数会被继承,产生一些问题;同时我们在自定义operator new函数时候需要考虑生成失败的情况。

针对operator delete函数,只需要记住的唯一事情就是C++保证“删除null指针永远安全”,所以必须兑现这项承诺。

void operator delete(void* rawMemory) throw(){
    if(rawMemory==0) return;//如果被删除的是个null指针,那就什么也不用做
    现在,归还rawMemory所指的内存;
}

下面,我们写一个较为健全的程序,定义operator new和operator delete。

class 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 delete(void* rawMeomory,std::size_t size) throw(){
    if(rawMemory==0) return;
    if(size!=sizeof(Base)){
        ::operator delete(rawMemory);
        return;
    }
    现在,归还rawMemory所指的内存;
    return;
}

总结:
1)operator new应该内含一个 无穷循环,并在其中尝试分配内存,如果它无法满足内存需求,就该调用new_handler。它也有能力处理0bytes申请,Cass专属版本则还应该处理“比正确大小更大(错误)的申请”;
2)operator delete应该在收到null指针时不做任何事,Class专属版本还应该处理“比正确大小更大的(错误)申请”。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值