• 读书笔记:Effective C++ 2.0 版,条款6(析构时delete)、7(内存不足)


    条款6: 析构函数里对指针成员调用delete
    指针管理,应该明确其生存周期、new delete mana策略。
    构造函数中new,在析构函数中delete,是一种简单可行的方案。虽然并不是适用于所有情况,有基本规则总是好的。
    写过一个内存管理的代码,需要支持内存数据的递归式联动,外加撤消重做(撤销重做后依然支持内存数据的递归联动)。从实践来看,在有限可控的函数中执行new delete,配合set、map,实际是比较容易实现内存的垃圾回收机制的。
    减少new、delete的使用,更应该被提倡。尽量用函数局部栈内对象,可以避免new、delete的内存管理,减少内存碎片,提高效率、稳定性。
    另外,重新强调c的malloc、free是没有构造析构的,可控性更好。

    条款7: 预先准备好内存不够的情况
    c风格

    typedef void (*new_handler)();
    new_handler set_new_handler(new_handler p) throw();
    // function to call if operator new can't allocate enough memory
    void nomorememory(){
    	cerr << "unable to satisfy request for memory\n";
    	abort();
    }
    int main(){
    	set_new_handler(nomorememory);
    	int *pbigdataarray = new int[100000000];
    	...	
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    cpp模板风格

    template<class t>	// 提供类set_new_handler支持的
    class newhandlersupport {	// 混合风格”的基类
    public:
    	static new_handler set_new_handler(new_handler p);
    	static void * operator new(size_t size);
    private:
    	static new_handler currenthandler;
    };
    template<class t>
    new_handler newhandlersupport<t>::set_new_handler(new_handler p){
    	new_handler oldhandler = currenthandler;
    	currenthandler = p;
    	return oldhandler;
    }
    template<class t>
    void * newhandlersupport<t>::operator new(size_t size){
    	new_handler globalhandler = std::set_new_handler(currenthandler);
    	void *memory;
    	try {
    		memory = ::operator new(size);
    	}
    	catch (std::bad_alloc&) {
    		std::set_new_handler(globalhandler);
    		throw;
    	}	
    	std::set_new_handler(globalhandler);
    	return memory;
    }
    // this sets each currenthandler to 0
    template<class t>
    new_handler newhandlersupport<t>::currenthandler;
    // note inheritance from mixin base class template. (see
    // my article on counting objects for information on why
    // private inheritance might be preferable here.)
    class x: public newhandlersupport<x> {
    ...		// as before, but no declarations for
    };		// set_new_handler or operator new
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    书中认为:使用set_new_handler是处理内存不够情况下一种方便、简单的方法。这比把每个new都包装在try模块里当然好多了。
    我个人都没有使用,常用的方法是在main中写一个try catch兜底,输出标准异常的信息即可。
    另外就是,可以考虑,32位程序在new之前进行内存可用值的判断。过多内存的情况下,内存实际可以new出来,但会触发许系统的内存回收和整理?win下有长时间卡顿情况。
    64位程序基本就不太需要考虑这个了。
    64位程序需要考虑的是内存消耗过大,导致的效率问题,需要考虑实时动态预警和自动处理。

  • 相关阅读:
    62.WEB渗透测试-信息收集- WAF、框架组件识别(2)
    java计算机毕业设计河南口腔医疗机构线上服务系统MyBatis+系统+LW文档+源码+调试部署
    剪映PC版英文字幕翻译最新方法(中英互译)
    pyqt6 vscode
    包管理工具之npm也慌了?
    闭区间上连续函数的一些定理
    博客问题处理之wordpress自动升级后如何降版本和禁止更新​
    记一个 Nvidia Control Panel 打不开的问题
    TCP 的自然律
    SpringBoot SpringBoot 原理篇 1 自动配置 1.6 bean 的加载方式【四】
  • 原文地址:https://blog.csdn.net/weixin_43172531/article/details/133872664