boost::weak_ptr 属于 boost 库,定义在 namespace boost 中,包含头文件 #include<boost/smart_ptr.hpp> 便可以使用。
在讲 boost::weak_ptr 之前,让我们先回顾一下前面讲解的内容。似乎 boost::scoped_ptr、boost::shared_ptr 这两个智能指针就可以解决所有单个对象内存的管理了,这儿还多出一个 boost::weak_ptr,
weak_ptr被设计为shared_ptr的助手,可以从一个shared_ptr或者另一个weak_ptr对象构造,获得资源的观测权,但是weak_ptr没有去共享资源,它的构造不会引起指针引用计数的增加,同样,weak_ptr析构也不会引起指针引用计数的减少
使用情况:
parent_ptr father(
new
parent());
children_ptr son( new children);
father->children = son;
son->parent = father;
children_ptr son( new children);
father->children = son;
son->parent = father;
运行该程序可以看到,即使退出了test函数后,由于parent和children对象互相引用,它们的引用计数都是1,不能自动释放,并且此时这两个对象再无法访问到。这就引起了c++中那臭名昭著的内存泄漏。
一般来讲,解除这种循环引用有下面有三种可行的方法:
-
当只剩下最后一个引用的时候需要手动打破循环引用释放对象。
-
当parent的生存期超过children的生存期的时候,children改为使用一个普通指针指向parent。
-
使用弱引用的智能指针打破这种循环引用。
虽然这三种方法都可行,但方法1和方法2都需要程序员手动控制,麻烦且容易出错。这里主要介绍一下第三种方法和boost中的弱引用的智能指针boost::weak_ptr。这样能破坏循环!
weak_ptr没有重载operator*和operator->,这是特意的。但是可以使用一个非常重要的成员函数lock(),从被观测的shared_ptr获得一个可用的shared_ptr对象,当被观察的 boost::shared_ptr 失效后,相应的 boost::weak_ptr 也相应失效。
class Simple {
public:
public:
Simple(int param = 0) {
number = param;
std::cout << "Simple: " << number << std::endl;
}
~Simple() {
std::cout << "~Simple: " << number << std::endl;
}
void PrintSomething() {
std::cout << "PrintSomething: " << info_extend.c_str() << std::endl;
}
number = param;
std::cout << "Simple: " << number << std::endl;
}
~Simple() {
std::cout << "~Simple: " << number << std::endl;
}
void PrintSomething() {
std::cout << "PrintSomething: " << info_extend.c_str() << std::endl;
}
public:
std::string info_extend;
int number;
};
std::string info_extend;
int number;
};
//测试函数
void TestWeakPtr() {
boost::weak_ptr<Simple> my_memory_weak;
boost::shared_ptr<Simple> my_memory(new Simple(1));
std::cout << "TestWeakPtr boost::shared_ptr UseCount: " << my_memory.use_count() << std::endl;
my_memory_weak = my_memory;
std::cout << "TestWeakPtr boost::shared_ptr UseCount: " << my_memory.use_count() << std::endl;
}
boost::weak_ptr<Simple> my_memory_weak;
boost::shared_ptr<Simple> my_memory(new Simple(1));
std::cout << "TestWeakPtr boost::shared_ptr UseCount: " << my_memory.use_count() << std::endl;
my_memory_weak = my_memory;
std::cout << "TestWeakPtr boost::shared_ptr UseCount: " << my_memory.use_count() << std::endl;
}
//主函数
int _tmain(int argc, _TCHAR* argv[])
{
TestSharedArray();
return 0;
}
{
TestSharedArray();
return 0;
}
执行结果为:
Simple: 1
TestWeakPtr boost::shared_ptr UseCount: 1
TestWeakPtr boost::shared_ptr UseCount: 1
~Simple: 1
我们看到,尽管被赋值了,内部的引用计数并没有什么变化,当然,读者也可以试试传递参数等其他情况。
现在要说的问题是,boost::weak_ptr 到底有什么作用呢?从上面那个例子看来,似乎没有任何作用,其实 boost::weak_ptr 主要用在软件架构设计中,可以在基类(此处的基类并非抽象基类,而是指继承于抽象基类的虚基类)中定义一个 boost::weak_ptr,用于指向子类的 boost::shared_ptr,这样基类仅仅观察自己的 boost::weak_ptr 是否为空就知道子类有没对自己赋值了,而不用影响子类 boost::shared_ptr 的引用计数,用以降低复杂度,更好的管理对象。