什么时候是std :: weak_ptr有用?

我开始研究C ++ 11的智能指针,我没有看到任何有用的std::weak_ptr 。 有人可以告诉我什么时候std::weak_ptr是有用的/必要的?

一个很好的例子是一个caching。

对于最近访问的对象,你想把它们保存在内存中,所以你持有一个强大的指针。 定期扫描caching并确定哪些对象最近未被访问。 你不需要把这些留在记忆里,所以你摆脱了强大的指针。

但是如果这个对象正在被使用,而其他的代码有一个强大的指针呢? 如果caching摆脱它唯一的指向对象的指针,它永远不会再find它。 所以如果caching保存在内存中,caching会保留一个弱对象指针。

这正是弱指针的作用 – 它允许您定位一个对象,如果它仍然在附近,但是如果没有其他东西需要它,则不会保留它。

std::weak_ptr是解决悬挂指针问题的一个很好的方法。 通过使用原始指针,不可能知道被引用的数据是否已经被释放。 相反,通过让std::shared_ptrpipe理数据,并为数据的用户提供std::weak_ptr ,用户可以通过调用expired()lock()来检查数据的有效性。

你不能单独使用std::shared_ptr来实现,因为所有的std::shared_ptr实例共享了在std::shared_ptr所有实例都被删除之前没有被删除的数据的所有权。 这是一个如何使用lock()检查悬挂指针的例子:

 #include <iostream> #include <memory> int main() { // OLD, problem with dangling pointer // PROBLEM: ref will point to undefined data! int* ptr = new int(10); int* ref = ptr; delete ptr; // NEW // SOLUTION: check expired() or lock() to determine if pointer is valid // empty definition std::shared_ptr<int> sptr; // takes ownership of pointer sptr.reset(new int); *sptr = 10; // get pointer to data without taking ownership std::weak_ptr<int> weak1 = sptr; // deletes managed object, acquires new pointer sptr.reset(new int); *sptr = 5; // get pointer to new data without taking ownership std::weak_ptr<int> weak2 = sptr; // weak1 is expired! if(auto tmp = weak1.lock()) std::cout << *tmp << '\n'; else std::cout << "weak1 is expired\n"; // weak2 points to new data (5) if(auto tmp = weak2.lock()) std::cout << *tmp << '\n'; else std::cout << "weak2 is expired\n"; } 

另一个答案,希望更简单。 (对于谷歌同行)

假设你有TeamMember对象。

显然这是一种关系: Team对象会指向其Members 。 而且成员可能也会有一个指向他们的Team对象的指针。

那么你有一个依赖周期。 如果你使用shared_ptr ,当你放弃引用时,对象将不再被自动释放,因为它们以循环的方式相互引用。 这是一个内存泄漏。

你可以使用weak_ptr这个问题。 “所有者”通常使用shared_ptr ,“拥有”使用weak_ptr给它的父节点,并在需要访问父节点时临时将其转换为shared_ptr

存储一个弱ptr:

 weak_ptr<Parent> parentWeakPtr_ = parentSharedPtr; // automatic conversion to weak from shared 

然后在需要时使用它

 shared_ptr<Parent> tempParentSharedPtr = parentWeakPtr_.lock(); // on the stack, from the weak ptr if( not tempParentSharedPtr ) { // yes it may failed if parent was freed since we stored weak_ptr } else { // do stuff } // tempParentSharedPtr is released when it goes out of scope 

下面是@jleahy给我的一个例子:假设你有一个asynchronous执行的任务集合,并由std::shared_ptr<Task> 。 你可能想定期做这些任务,所以一个定时器事件可能会遍历一个std::vector<std::weak_ptr<Task>>并给这个任务做些事情。 然而,同时一个任务可能同时决定不再需要和死亡。 定时器可以通过从弱指针创build共享指针并使用该共享指针(如果它不为空)来检查该任务是否仍然存在。

weak_ptr也很好地检查对象的正确删除 – 特别是在unit testing中。 典型的用例可能如下所示:

 std::weak_ptr<X> weak_x{ shared_x }; shared_x.reset(); BOOST_CHECK(weak_x.lock()); ... //do something that should remove all other copies of shared_x and hence destroy x BOOST_CHECK(!weak_x.lock()); 

shared_ptr :保存真实的对象。

weak_ptr :使用lock连接到真正的所有者,否则返回NULL。

弱ptr

粗略地说, weak_ptr作用类似于住房机构的作用。 如果没有代理商,要租房子,我们可能需要检查城市中的随机房屋。 代理商确保我们只访问那些仍然可以出租的房屋。

当你不能保证当一个asynchronous处理程序被调用时目标对象仍然存在时,它们对Boost.Asio很有用。 诀窍是使用std::bind或lambda捕获将weak_ptr绑定到asynchronous处理程序对象。

 void MyClass::startTimer() { std::weak_ptr<MyClass> weak = shared_from_this(); timer_.async_wait( [weak, this](const boost::system::error_code& ec) { auto self = weak.lock(); if (self) { self->handleTimeout(); } else { std::cout << "Target object no longer exists!\n"; } } ); } 

这是Boost.Asio中经常见到的self = shared_from_this()成语的一个变体,其中一个挂起的asynchronous处理程序不会延长目标对象的生存期,但如果目标对象被删除仍然是安全的。

http://en.cppreference.com/w/cpp/memory/weak_ptr std :: weak_ptr是一个智能指针,它拥有一个由std :: shared_ptrpipe理的对象的非拥有(“弱”)引用。 它必须转换为std :: shared_ptr才能访问被引用的对象。

std :: weak_ptr模拟临时所有权:当一个对象需要被访问时,只要它存在,并且可能被其他人随时删除,std :: weak_ptr被用来跟踪对象,并被转换为std: :shared_ptr承担临时所有权。 如果原来的std :: shared_ptr在这个时候被销毁,那么对象的生命周期就会被延长,直到临时的std :: shared_ptr被销毁。

另外,std :: weak_ptr被用来打破std :: shared_ptr的循环引用。

共享指针有一个缺点:shared_pointer不能处理父子循环依赖。 意思是如果父类使用共享指针的子类对象,如果子类使用父类的对象,则在相同的文件中。 共享指针将无法破坏所有对象,甚至共享指针在循环依赖场景中根本不会调用析构函数。 基本上共享指针不支持引用计数机制。

这个缺点我们可以用weak_pointer来克服。