effective c++读书笔记(八)

定制new和delete

主角是operator new 和operator delete,配角是new-handler,当operator new无法满足客户的内存需求时所调用的函数。
多线程环境下的内存管理,比单线程复杂的多。由于heap是一个可悲改动的全局性资源,因此多线程系统充斥这发狂访问这一类资源的race conditions出现机会。

了解new-handler的行为

namespace std{
    typedef void (*new_handler)();
    new_handler set_new_handler(new_handler p) throw();
}

一个设计良好的new-handler函数必须做以下事情:
1.让更多内存可被使用。实现此策略的做法是,程序一开始执行就分配一大块内存,而后当new-handler第一次调用时,将它们释放还给程序使用。
2.安装另一个new-handler。就是说目前这个new-handler无法取得更多的内存,如果另外一个new-handler有这个能力,应该调用另外一个new-handler来完成这个任务。实现方法:令new-handler修改会影响new-handler行为的static数据,namespace数据和global数据。
3.卸除new-handler。将null指针传给set_new_handler。一旦没有安装任何new-handler,operator new会在内存分配不成功时抛出异常
4.抛出bad_alloc的异常。这样的异常不会被operator new 捕捉,因此会被传播到内存索求处。
5.不返回。通常调用abort或exit。

了解new和delete的合理替换时机

替换编译器提供的operator new或operator delete的理由:
1. 用来检测运用上的错误。
2. 为了强化效能。
3. 为了收集使用上的统计数据。
4. 为了增加分配和归还的速度。
5. 为了降低缺省内存管理器带来的空间额外开销
6. 为了弥补缺省分配器中的非最佳齐位
7. 为了将相关对象成簇集中。
8. 为了获得非传统行为

编写new和delete时需固守常规

实现一致性operator new必须返回正确的值,内存不足时必得调用new-handling函数,必须有对付零内存需求的准备,还需避免不慎遮盖正常形式的new–虽然这比较偏近class的接口要求而非实现要求。

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-handling函数
        new_handler globalHandler = set_new_handler(0);
        set_new_handler(globalHandler);

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

继承operator new成员函数的derived class会导致怪异的问题。

class Base{
public:
    void* operator new(std::size_t size) throw(std::bad_alloc);
};
class Derived : public Base{  //...}

Derived *p = new Derived;

void* Base::operator new(std::size_t size) throw(std::bad_alloc){
    if(size != sizeof(Base))  //针对继承class出现问题
        return ::operator new(size);
    //...
}

如果决定写个operator new[],唯一需要做的就是分配一块未加工的内存,因为无法对array内迄今尚未存在的元素对象做任何事情。

operator delete,需要保证删除null指针永远安全。

void operator delete(void *rawMemory) throw(){
    if(rawMemory == 0) return ;
    //.... 归还rawMemory所指的内存
}

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* rawMemory, std::size_t size) throw(){
    if(rawMemory == 0 ) return;
    if(size != sizeof(Base)){    //如果大小错误,调用标准版operator delete处理
        ::operator delete(rawMemory);
        return;
    }
    //归还rawMemory所指内存
    return;
}

写了placement new也要写placement delete

如果一个带额外参数的operator new没有带相同额外参数的对应版operator delete,那么当new的内存分配动作需要取消并恢复旧观时就没有任何operator delete会被调用。

class Widget{
public:
    static void* operator new(std::size_t size, std::ostream& logStream) throw(std::bad_alloc);
    static void operator delete(void* memory) throw();   //必须的
    static void operator delete(void* memory, std::ostream& logStream) throw();  //必须的
};

Widget* pw = new(std::cerr) Widget;  //抛出异常时,不会导致内存泄漏,可以恢复如初

如果你在class内声明任何operator news,它会遮蔽上述的标准形式,实现所有自定义的new和标准的new都可以用的简单做法就是,建立一个base class,内含所有正常形式的new和delete

class StandardNewDeleteForms{
public:
    static void* operator new(std::size_t size) throw(std::bad_alloc){
        return ::operator new(size);
    }
    static void operator delete(void* memory) throw(){
        ::operator delete(memory);
    }
    static void* operator new(std::size_t size, void* ptr) throw(){
        return ::operator new(size,ptr);
    }
    static void operator delete(void* memory, void* ptr) throw(){
        return ::operator delete(memory,ptr);
    }
    static void* operator new(std::size_t size, const std::nothrow_t& nt) throw(){
        return ::operator new(size,nt);
    }
    static void operator delete(void* memory,const std::nothrow_t&) throw(){
        ::operator delete(memory);
    }
};

然后可以通过using声明式来获取标准形式

class Widget: public StandardNewDeleteForms{
public:
    using StandardNewDeleteForms::operator new;
    using StandardNewDeleteForms::operator delete;
    static void* operator new(std::size_t size, std::ostream& logStream) throw(std::bad_alloc);
    static void operator delete(void* memory, std::ostream& logStream) throw();
    //...
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
城市应急指挥系统是智慧城市建设的重要组成部分,旨在提高城市对突发事件的预防和处置能力。系统背景源于自然灾害和事故灾难频发,如汶川地震和日本大地震等,这些事件造成了巨大的人员伤亡和财产损失。随着城市化进程的加快,应急信息化建设面临信息资源分散、管理标准不统一等问题,需要通过统筹管理和技术创新来解决。 系统的设计思路是通过先进的技术手段,如物联网、射频识别、卫星定位等,构建一个具有强大信息感知和通信能力的网络和平台。这将促进不同部门和层次之间的信息共享、交流和整合,提高城市资源的利用效率,满足城市对各种信息的获取和使用需求。在“十二五”期间,应急信息化工作将依托这些技术,实现动态监控、风险管理、预警以及统一指挥调度。 应急指挥系统的建设目标是实现快速有效的应对各种突发事件,保障人民生命财产安全,减少社会危害和经济损失。系统将包括预测预警、模拟演练、辅助决策、态势分析等功能,以及应急值守、预案管理、GIS应用等基本应用。此外,还包括支撑平台的建设,如接警中心、视频会议、统一通信等基础设施。 系统的实施将涉及到应急网络建设、应急指挥、视频监控、卫星通信等多个方面。通过高度集成的系统,建立统一的信息接收和处理平台,实现多渠道接入和融合指挥调度。此外,还包括应急指挥中心基础平台建设、固定和移动应急指挥通信系统建设,以及应急队伍建设,确保能够迅速响应并有效处置各类突发事件。 项目的意义在于,它不仅是提升灾害监测预报水平和预警能力的重要科技支撑,也是实现预防和减轻重大灾害和事故损失的关键。通过实施城市应急指挥系统,可以加强社会管理和公共服务,构建和谐社会,为打造平安城市提供坚实的基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值