• 不要让继承自引用计数管理资源的对象在栈上实例


    引用计数进行管理资源,我们最熟悉的就是智能指针。在c++11之前,我们的对象都从一个引用计数管理资源的类继承,这个类有一个引用计数器,两个配对的操作addref和delref,当delref将引用计数器减为0时,会自动调用delete。这种机制要求对象必须实例在堆上,也就是new创建。当决定继承一个对象时,你必须小心看一遍它的继承树,是否继承了这一种的类。

    一旦你将使用引用计数管理资源的对象在栈上实例后,这个对象就有可能被栈和堆同时管理资源。首先在栈实例后,这个对象一定会在栈帧作用域内被管理资源,当离开栈帧时对象被释放。如果有一个函数很深层调用,或这个对象的某个接口函数将这个对象的指针送进了智能指针,这时就带来灾难了,这个对象又被堆管理上资源了。当这个意外的智能指针销毁时,这个栈上对象却用堆来管理资源了。或者这个意外的智能指针保留了一个野指针,栈对象已经离开作用域。

    IceUtil::Thread就是一个例子。在主线程的栈上实例这些继承来的线程对象,然后开始这些线程,在主线程退出前停止这些线程,线程对象离开局部作用域对象被栈回收。但问题来了,IceUtil::Thread is a IceUtil::Shared,这个IceUtil::Shared就是一个引用计数管理资源的类。IceUtil::Thread::start(),这个接口在开始一个线程时,将线程对象以智能指针方式作为线程参数了,换句话说这个智能指针生命期与新线程相随。当主线程栈上的线程对象停止线程时,线程在退出时线程对象因为智能指针而被delete,灾难发生了。

    boost::thread,IceUtil::Thread或其它框架库都有封装线程类,大家的设计的思想大致也都为重写run虚函数,start启动线程,stop停止线程。但是使用上细节不是全盘通用的。boost::thread可以在栈上实例,但IceUtil::Thread就小心了。

  • 相关阅读:
    Java21-统计字符串中每个字符出现的次数
    算法练习之字符串切割及统计每个字符出现的次数
    Java20-HashMap
    Java19-hashSet
    Java18-泛型的基础知识
    Java17-foreach循环遍历
    Java16-【转载】ArrayList和LinkedList的区别
    Unity查看Editor下PlayerPrefs信息
    Unity下自定义快捷键创建UGUI元素
    Unity中去除贴图中多余的透明区域
  • 原文地址:https://www.cnblogs.com/bbqzsl/p/7662164.html
Copyright © 2020-2023  润新知