C++内存管理学习笔记(5) (三)

2014-11-24 00:56:18 · 作者: · 浏览: 7
于多线程同是访问智能指针,并将其赋值到其它同类智能指针时,很可能发生两个线程同时在操作引用计数(但并不一定绝对发生),而导致计数失败或无效等情况,从而导致程序崩溃,如若不知根源,就无法查找这个bug,那就只能向上帝祈祷程序能正常运行。

可能一般情况下并不会写出上面这样的代码,但是下面这种代码与上面的代码同样,如下:

1: class tester 2: { 3: public: 4: tester() {} 5: ~tester() {} 6: public: 7: boost::shared_ptr m_spData; // 可能其它类型。 8: }; 9: tester gObject; 10: void fun(void) 11: { 12: // !!!在这大量使用sp指针. 13: boost::shared_ptr tmp = gObject.m_spData; 14: } 15: int main() 16: { 17: // 多线程。 18: boost::thread t1(&fun); 19: boost::thread t2(&fun); 20: t1.join(); 21: t2.join(); 22: return 0; 23: }
情况是一样的。要解决这类问题的办法也很简单,使用boost.weak_ptr就可以很方便解决这个问题。第一种情况修改代码如下:

1: class tester 2: { 3: public: 4: tester() {} 5: ~tester() {} 6: // 更多的函数定义… 7: }; 8: void fun(boost::weak_ptr wp) 9: { 10: boost::shared_ptr sp = wp.lock; 11: if (sp) 12: { 13: // 在这里可以安全的使用sp指针. 14: } 15: else 16: { 17: std::cout << “指针已被释放!” << std::endl; 18: } 19: } 20: int main() 21: { 22: boost::shared_ptr sp1(new tester); 23: boost.weak_ptr wp(sp1); 24: // 开启两个线程,并将智能指针传入使用。 25: boost::thread t1(boost::bind(&fun, wp)); 26: boost::thread t2(boost::bind(&fun, wp)); 27: t1.join(); 28: t2.join(); 29: return 0; 30: }
boost.weak_ptr指针功能一点都不weak,weak_ptr是一种可构造、可赋值以不增加引用计数来管理shared_ptr的指针,它可以方便的转回到shared_ptr指针,使用weak_ptr.lock函数就可以得到一个shared_ptr的指针,如果该指针已经被其它地方释放,它则返回一个空的shared_ptr,也可以使用weak_ptr.expired()来判断一个指针是否被释放。

boost.weak_ptr不仅可以解决多线程访问带来的安全问题,而且还可以解决上面第三个问题循环引用。Children类代码修改如下,即可打破循环引用:

1: class child 2: { 3: public: 4: ~child() { 5: std::cout <<"子类析构函数被调用.\n"; 6: } 7: public: 8: boost::weak_ptr parent; 9: };
因为boost::weak_ptr不增加引用计数,所以可以在退出函数域时,正确的析构。