空悬指针:
当有两个指针同时指向一个对象时,如果只有一个指针对对象进行了销毁,哪怕后续做的再好,那另一个指针就是空悬指针了。
一个“解决办法”
我的老师教过我,一旦有了困难,先想想能不能加入间接层,一旦问题复杂化,牵涉过多,就引入间接层,这是一种思想,就和不要使用一个变量表达多种含义一样,宁可多设置变量,毕竟变量的开销较小。
在这里,可以引入一个间接层,让两个指针指向的都是间接层,一旦想要释放对象,则通过间接层释放即可,然后将间接层的指针指向NULL,则不用管多少指针还指向它,都不会出错,只要每次其他指针判断是否为NULL即可。
但要线程安全的释放对象也存在上次的问题。
一个更好的解决办法:
就是shared_ptr智能指针的思想,引入引用计数,只要保证引用计数的线程安全性,则整体就是线程安全的了,而C++的TR1标准库里就存在:shared_ptr和weak_ptr。
shared_ptr/weak_ptr
shared_ptr是引用计数型智能指针,在Boost和tr1里均提供,也被纳入C11标准,现代主流的C++编译器都能很好地支持。shared_ptr<T>是一个类模板,它只有一个类型参数,使用起来很方便。引用计数是自动化管理的常用手法,当引用计数降为0时,对象(资源即被销毁)。weak_ptr也是一个引用计数型智能指针,但是它不增加对象的引用次数。
shared_ptr控制对象的生命期。shared_ptr是强引用,只要有一个shared_ptr指针存在(引用计数>= 1),指向的对象就不会析构。当最后一个指针析构或reset()的时候,对象保证会被销毁。
weak_ptr不控制对象的生命期,但它知道对象是否存在,如果存在,它可以提升为shared_ptr;如果不存在,提升会失败,将指向为NULL,但它此时已经是shared_ptr;提升/lock()行为是线程安全的。
shared_ptr和weak-ptr的“计数”在主流平台上是原子操作,且没有用锁,所以高效。但她们的线程安全级别与string和STL容器一样。