在C++中,动态内存的管理是通过一对运算符来完成的:new,在动态内存中为对象分配空间并返回一个指向该对象的指针,可以选择对对象进行初始化;delete,接受一个动态对象的指针,销毁该对象,并释放与之关联的内存。

动态内存的使用很容易出问题,因为确保在正确的时间释放内存是极其困难的。有时会忘记释放内存,在这种情况下会产生内存泄露;有时在尚有指针引用内存的情况下就释放了它,在这种情况下就会产生引用非法内存的指针。

为了更容易(同时也更安全)地使用动态内存,C++11标准库提供了两种智能指针(smart pointer)类型来管理动态对象。智能指针的行为类似常规指针,重要的区别是它负责自动释放所指的对象。C++11标准库提供的这两种智能指针的区别在于管理底层指针的方式:shared_ptr允许多个指针指向同一个对象;unique_ptr则"独占"所指向的对象。C++11标准库还定义了一个名为weak_ptr的辅助类,它是一种弱引用,指向shared_ptr所管理的对象。这三种类型都定义在memory头文件中。智能指针是模板类而不是指针。类似vector,智能指针也是模板,当创建一个智能指针时,必须提供额外的信息即指针可以指向的类型。默认初始化的智能指针中保存着一个空指针。智能指针的使用方式与普通指针类似。解引用一个智能指针返回它指向的对象。如果在一个条件判断中使用智能指针,效果就是检测它是否为空。

Pointer misuse can be a major source of bugs. Smart pointers prevent most situations of memory leaks by making the memory deallocation automatic. More generally, they make object destruction automatic: an object controlled by a smart pointer is automatically destroyed (finalized and then deallocated) when the last (or only) owner of an object is destroyed.

In C++, a smart pointer is implemented as a template class that mimics, by means of operator overloading, the behaviors of a traditional (raw) pointer, while providing additional memory management features.

std::weak_ptr is a smart pointer that holds a non-owning ("weak") reference to an object that is managed by std::shared_ptr. It must be converted to std::shared_ptr in order to access the referenced object.

std::weak_ptr models temporary ownership: when an object needs to be accessed only if it exists, and it may be deleted at any time by someone else, std::weak_ptr is used to track the object, and it is converted to std::shared_ptr to assume temporary ownership. If the original std::shared_ptr is destroyed at this time,the object's lifetime is extended until the temporary std::shared_ptr is destroyed as well.

In addition,std::weak_ptr is used to break circular references of std::shared_ptr.

weak_ptr is primarily useful in the rare cases where it is needed in order to break'circular references' – a problem with the use of reference counting in shared_ptr.

Sometimes an object must store a way to access the underlying object of a shared_ptr without causing the reference count to be incremented. Typically, this situation occurs when you have cyclic references between shared_ptr instances. The best design is to avoid shared ownership of pointers whenever you can. However, if you must have shared ownership of shared_ptr instances, avoid cyclic references between them. When cyclic references are unavoidable, or even preferable for some reason, use weak_ptr to give one or more of the owners a weak reference to another shared_ptr. By using a weak_ptr, you can create a shared_ptr that joins to an existing set of related instances, but only if the underlying memory resource is still valid. A weak_ptr itself does not participate in the reference counting, and therefore, it cannot prevent the reference count from going to zero. However, you can use a weak_ptr to try to obtain a new copy of the shared_ptr with which it was initialized. If the memory has already been deleted, a bad_weak_ptr exception is thrown. If the memory is still valid, the new shared pointer increments the reference count and guarantees that the memory will be valid as long as the shared_ptr variable stays in scope.

weak_ptr被设计为与shared_ptr共同工作,可以从一个shared_ptr或者另一个weak_ptr对象构造,获得资源的观测权。但weak_ptr没有共享资源,它的构造不会引起指针引用计数的增加。同样,在weak_ptr析构时也不会导致引用计数的减少,它只是一个静静地观察者。weak_ptr没有重载operator*和->,这是特意的,因为它不共享指针,不能操作资源,这是它弱的原因。但它可以使用一个非常重要的成员函数lock()从被观测的shared_ptr获得一个可用的shared_ptr对象,从而操作资源。

weak_ptr用于解决”引用计数”模型循环依赖问题,weak_ptr指向一个对象,并不增减该对象的引用计数器。weak_ptr用于配合shared_ptr使用,并不影响动态对象的生命周期,即其存在与否并不影响对象的引用计数器。weak_ptr并没有重载operator->和operator *操作符,因此不可直接通过weak_ptr使用对象。weak_ptr提供了expired()与lock()成员函数,前者用于判断weak_ptr指向的对象是否已被销毁,后者返回其所指对象的shared_ptr智能指针(对象销毁时返回”空”shared_ptr)。

智能指针是模板类而不是指针.

weak_ptr并没有重载operator->和operator *操作符,因此不可直接通过weak_ptr使用对象,典型的用法是调用其lock函数来获得shared_ptr示例,进而访问原始对象。

weak_ptr是一种不控制所指向对象生存期的智能指针,它指向由一个shard_ptr管理的对象。将一个weak_ptr绑定到一个shared_ptr不会改变shared_ptr的引用计数。一旦最后一个指向对象的shared_ptr被销毁,对象就会被释放。即使有weak_ptr指向对象,对象也还是会被释放。

当创建一个weak_ptr时,要用一个shared_ptr来初始化它。不能使用weak_ptr直接访问对象,而必须调用lock。此函数检查weak_ptr指向的对象是否仍存在。如果存在,lock返回一个指向共享对象的shared_ptr。与任何其它shared_ptr类似,只要此shared_ptr存在,它所指向的底层对象也就会一直存在。

下图列出了weak_ptr支持的操作(来源于C++ Primer Fifth Edition 中文版):

下面是从其他文章中copy的测试代码,详细内容介绍可以参考对应的reference:
#include "weak_ptr.hpp"
#include <iostream>
#include <memory>
#include <algorithm>
#include <string>
#include <vector>///
// reference: http://en.cppreference.com/w/cpp/memory/weak_ptr
std::weak_ptr<int> gw;void f()
{if (auto spt = gw.lock()) { // Has to be copied into a shared_ptr before usagestd::cout << *spt << "\n";}else {std::cout << "gw is expired\n";}
}int test_weak_ptr1()
{{auto sp = std::make_shared<int>(42);gw = sp;f();}f();return 0;
}/
// reference: http://stackoverflow.com/questions/12030650/when-is-stdweak-ptr-useful
int test_weak_ptr2()
{// 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 definitionstd::shared_ptr<int> sptr;// takes ownership of pointersptr.reset(new int);*sptr = 10;// get pointer to data without taking ownershipstd::weak_ptr<int> weak1 = sptr;// deletes managed object, acquires new pointersptr.reset(new int);*sptr = 5;// get pointer to new data without taking ownershipstd::weak_ptr<int> weak2 = sptr;// weak1 is expired!if (auto tmp = weak1.lock())std::cout << *tmp << '\n';elsestd::cout << "weak1 is expired\n";// weak2 points to new data (5)if (auto tmp = weak2.lock())std::cout << *tmp << '\n';elsestd::cout << "weak2 is expired\n";return 0;
}//
// reference: https://msdn.microsoft.com/en-us/library/hh279672.aspx
class Controller
{
public:int Num;std::string Status;std::vector<std::weak_ptr<Controller>> others;explicit Controller(int i) : Num(i), Status("On"){std::cout << "Creating Controller" << Num << std::endl;}~Controller(){std::cout << "Destroying Controller" << Num << std::endl;}// Demonstrates how to test whether the pointed-to memory still exists or not.void CheckStatuses() const{for_each(others.begin(), others.end(), [](std::weak_ptr<Controller> wp) {try {auto p = wp.lock();std::cout << "Status of " << p->Num << " = " << p->Status << std::endl;}catch (std::bad_weak_ptr b) {std::cout << "Null object" << std::endl;}});}
};void RunTest()
{std::vector<std::shared_ptr<Controller>> v;v.push_back(std::shared_ptr<Controller>(new Controller(0)));v.push_back(std::shared_ptr<Controller>(new Controller(1)));v.push_back(std::shared_ptr<Controller>(new Controller(2)));v.push_back(std::shared_ptr<Controller>(new Controller(3)));v.push_back(std::shared_ptr<Controller>(new Controller(4)));// Each controller depends on all others not being deleted.// Give each controller a pointer to all the others. for (int i = 0; i < v.size(); ++i) {for_each(v.begin(), v.end(), [v, i](std::shared_ptr<Controller> p) {if (p->Num != i) {v[i]->others.push_back(std::weak_ptr<Controller>(p));std::cout << "push_back to v[" << i << "]: " << p->Num << std::endl;}});}for_each(v.begin(), v.end(), [](std::shared_ptr<Controller>& p) {std::cout << "use_count = " << p.use_count() << std::endl;p->CheckStatuses();});
}int test_weak_ptr3()
{RunTest();std::cout << "Press any key" << std::endl;char ch;std::cin.getline(&ch, 1);return 0;
}// reference: https://oopscenities.net/2014/08/03/c-smart-pointers-part-5-weak_ptr/
struct Child;
struct Parent
{std::shared_ptr<Child> child;~Parent() { std::cout << "Bye Parent" << std::endl; }void hi() const { std::cout << "Hello" << std::endl; }
};struct Child
{std::weak_ptr<Parent> parent;//std::shared_ptr<Parent> parent; // memory leak~Child() { std::cout << "Bye Child" << std::endl; }
};int test_weak_ptr4()
{auto parent = std::make_shared<Parent>();auto child = std::make_shared<Child>();parent->child = child;child->parent = parent;child->parent.lock()->hi();// child->parent->hi();return 0;
}/
// reference: http://thispointer.com/shared_ptr-binary-trees-and-the-problem-of-cyclic-references/
class Node
{int value;
public:std::shared_ptr<Node> leftPtr;std::shared_ptr<Node> rightPtr;// Just Changed the shared_ptr to weak_ptrstd::weak_ptr<Node> parentPtr;Node(int val) : value(val)     {std::cout << "Contructor" << std::endl;}~Node()     {std::cout << "Destructor" << std::endl;}
};int test_weak_ptr5()
{std::shared_ptr<Node> ptr = std::make_shared<Node>(4);ptr->leftPtr = std::make_shared<Node>(2);ptr->leftPtr->parentPtr = ptr;ptr->rightPtr = std::make_shared<Node>(5);ptr->rightPtr->parentPtr = ptr;std::cout << "ptr reference count = " << ptr.use_count() << std::endl;std::cout << "ptr->leftPtr reference count = " << ptr->leftPtr.use_count() << std::endl;std::cout << "ptr->rightPtr reference count = " << ptr->rightPtr.use_count() << std::endl;std::cout << "ptr->rightPtr->parentPtr reference count = " << ptr->rightPtr->parentPtr.lock().use_count() << std::endl;std::cout << "ptr->leftPtr->parentPtr reference count = " << ptr->leftPtr->parentPtr.lock().use_count() << std::endl;return 0;
}

GitHub:https://github.com/fengbingchun/Messy_Test

C++11中weak_ptr的使用相关推荐

  1. C++11中unique_ptr的使用

    在C++中,动态内存的管理是通过一对运算符来完成的:new,在动态内存中为对象分配空间并返回一个指向该对象的指针,可以选择对对象进行初始化:delete,接受一个动态对象的指针,销毁该对象,并释放与之 ...

  2. c++11中智能指针的原理,使用,实现

    文章目录 理解智能指针的原理 智能指针的使用 shared_ptr的使用 unique_ptr的使用 weak_ptr的使用 循环引用 指针指针的设计和实现: 理解智能指针的原理 c++程序设计中使用 ...

  3. c++ 智能指针_详解 C++ 11 中的智能指针

    C/C++ 语言最为人所诟病的特性之一就是存在内存泄露问题,因此后来的大多数语言都提供了内置内存分配与释放功能,有的甚至干脆对语言的使用者屏蔽了内存指针这一概念.这里不置贬褒,手动分配内存与手动释放内 ...

  4. c++11中的智能指针

    在C++11中有四种智能指针,auto_ptr,shared-ptr,unique_ptr和weak-ptr,其中auto_ptr有许多不足之处,在C++11中已经建议废弃使用. 1. shared_ ...

  5. C++11中头文件type_traits介绍

    C++11中的头文件type_traits定义了一系列模板类,在编译期获得某一参数.某一变量.某一个类等等类型信息,主要做静态检查. 此头文件包含三部分: (1).Helper类:帮助创建编译时常量的 ...

  6. C++11中std::async的使用

    C++11中的std::async是个模板函数.std::async异步调用函数,在某个时候以Args作为参数(可变长参数)调用Fn,无需等待Fn执行完成就可返回,返回结果是个std::future对 ...

  7. C++11中std::packaged_task的使用

    C++11中的std::packaged_task是个模板类.std::packaged_task包装任何可调用目标(函数.lambda表达式.bind表达式.函数对象)以便它可以被异步调用.它的返回 ...

  8. C++11中std::shared_future的使用

    C++11中的std::shared_future是个模板类.与std::future类似,std::shared_future提供了一种访问异步操作结果的机制:不同于std::future,std: ...

  9. C++11中std::future的使用

    C++11中的std::future是一个模板类.std::future提供了一种用于访问异步操作结果的机制.std::future所引用的共享状态不能与任何其它异步返回的对象共享(与std::sha ...

最新文章

  1. Unobtrusive JavaScript 不唐突的JavaScript的七条准则
  2. MS SQL SERVER 中几个函数的用法
  3. CodeForces - 1300E Water Balance(贪心)
  4. Android 自定义View消除锯齿实现图片旋转,添加边框及文字说明
  5. oracle线程阻塞_Oracle Service Bus –线程阻塞案例研究
  6. 前端学习(2611):vuex实现增加
  7. Dubbo作者亲述:那些辉煌、沉寂与重生的故事 1
  8. IE6下溢出多余文字
  9. webpack查缺补漏
  10. 随机过程:鞅与马尔科夫过程的理解
  11. Atitit 软件知识点分类体系 分类 按照书籍的分类 学科分类 体系与基础部分 计算机体系结构 硬件接口技术(usb,agp,pci,div,hdmi) os操作系统 中间件 语言部分
  12. php代码审计系列教程,PHP代码审计工具——Rips详细使用教程
  13. Youtube优质游戏开发UP主推荐:JayAnAm
  14. 融资融券是对A股明显利好
  15. MultipartFile和File互转
  16. Python-爬虫(xpath数据解析,爬取信息实战)
  17. 认识计算机硬件教案免费,认识计算机硬件(教案)
  18. PowerBI-时间智能函数-LAST系列
  19. 【html】 把 a 标签的下滑线去掉
  20. 物联网(AIOT产业)应用简介

热门文章

  1. C指针4:数组指针(指向数组的指针)
  2. OpenCV(总结篇)图像逐像素访问(三种操作:指针、迭代器、at()函数)
  3. 数字图像处理——第六章 彩色图像处理
  4. 检测硬盘使用时长_如何检测硬盘问题
  5. C++中结构体与类的区别(struct与class的区别)
  6. 为方便ATS管理建立的一些命令别名
  7. LTE PUCCH Format1
  8. s32v 开发板安装 apex 驱动
  9. mono+jexus 部署之CompilationException
  10. 普通粒子群算法和优化方法