C++11: std::weak_ptr
1. 简介
weak_ptr
智能指针的一种,主要是为了解决shared_ptr
循环引用的问题。
2. 使用
weak_ptr
主要有两种构造方式,一种是从shared_ptr
,另外是一种是weak_ptr
。
下面是一个例子,use_count
是引用计数。
可以看到weak_ptr
并不会增加引用计数。
#include <iostream>
#include <memory>int main()
{std::shared_ptr<int> sp( new int);std::weak_ptr<int> wp1; std::weak_ptr<int> wp2(wp1);std::weak_ptr<int> wp3(sp);std::cout << "use_count" << '\n';std::cout << "wp1: " << wp1.use_count() << '\n';std::cout << "wp2: " << wp2.use_count() << '\n';std::cout << "wp3: " << wp3.use_count() << '\n';return 0;
}
输出
use_count
wp1: 0
wp2: 0
wp3: 1
由于我weak_ptr
只有对象的使用权而不管理对象的生命周期,
所以需要expired()
先来判断使用的这个对象有没有过期。
下面是一个例子
#include <iostream>
#include <memory>int main () {std::shared_ptr<int> shared (new int(10));std::weak_ptr<int> weak(shared);std::cout << "1. weak " << (weak.expired()?"is":"is not") << " expired\n";shared.reset();std::cout << "2. weak " << (weak.expired()?"is":"is not") << " expired\n";return 0;
}
reset
是将shared_ptr
所管理的对象给释放掉,换成新的或者置空。
输出的结果
1. weak is not expired
2. weak is expired
还有一个比较重要的方法是lock
是从weak_ptr
恢复一个shared_ptr
,如果对象没有过期的话。下面是一个例子。
#include <iostream>
#include <memory>int main () {std::shared_ptr<int> sp1,sp2;std::weak_ptr<int> wp;// sharing group:// --------------sp1 = std::make_shared<int> (20); // sp1wp = sp1; // sp1, wpsp2 = wp.lock(); // sp1, wp, sp2std::cout << "use_count: " << wp.use_count() << '\n';sp1.reset(); // wp, sp2std::cout << "use_count: " << wp.use_count() << '\n';sp1 = wp.lock(); // sp1, wp, sp2std::cout << "use_count: " << wp.use_count() << '\n';std::cout << "*sp1: " << *sp1 << '\n';std::cout << "*sp2: " << *sp2 << '\n';return 0;
}
结果
use_count: 2
use_count: 1
use_count: 2
*sp1: 20
*sp2: 20
3. 应用场景
- 解决循环引用
#include <iostream>
#include <memory>struct Node {Node(int v):v_(v){}std::shared_ptr<Node> next; // Points to the next nodestd::weak_ptr<Node> prev; // Points to the previous node~Node() {std::cout << "Node "<< v_ <<" destroyed\n";}int v_;
};int main() {auto node1 = std::make_shared<Node>(1);auto node2 = std::make_shared<Node>(2);node1->next = node2; // node1 points to node2node2->prev = node1; // node2 points to node1 using weak_ptrreturn 0; // No memory leak occurs due to the use of weak_ptr
}
输出结果
Node 1 destroyed
Node 2 destroyed
如果使用两个shared_ptr
相互之间等待,程序就不会正常退出了。
- 作缓存,只享用使用权不管理生命周期
class RuleHandle{std::weak_ptr<BasicRule> rule_weak_ptr_;public:template<class RuleType>explicit RuleHandle( const std::shared_ptr<RuleType> x ) : rule_weak_ptr_( x ){}void cancel();};
4. 参考
cplusplus.com
simplifycpp
qiang-zhihu