首页 > 编程语言 >C++智能指针:weak_ptr

C++智能指针:weak_ptr

时间:2023-06-05 11:00:23浏览次数:41  
标签:对象 weak C++ 引用 shared ptr 指针

weak_ptr虽然是智能指针,但实际上是作为shared_ptr的辅助指针使用。
weak_ptr通常不单独使用,一般用于查看对应的shared_ptr的信息。weak_ptr没有重载*,->等指针运算符。
weak_ptr对象不会影响shared_ptr对象的引用计数。

 

#include<iostream>
#include<string.h>
#include<memory>
#include<stdio.h>
using namespace std;

int main()
{
  //创建空weak_ptr对象
  weak_ptr<double> w1;

  /*注意:不能使用nullptr构造weak_ptr对象,这一点与shared_ptr,unique_ptr都不同!*/
  weak_ptr<double> w1(nullptr); //错误
  //使用拷贝构造函数初始化weak_ptr对象
  weak_ptr<double> w2(w1);
  /*
    使用shared_ptr对象初始化weak_ptr对象
    注意:即使通过shared_ptr对象初始化weak_ptr对象,shared_ptr对象的引用计数也不会发生变化。
  */
  shared_ptr<double> s3(new int(6));
  weak_ptr<double> w3(s3);
  weak_ptr<double> w4 = s3;

  //注意:不能使用堆指针初始化weak_ptr对象
  weak_ptr<double> w5(new double); //错误

  //weak_ptr类只重载了=赋值运算符,可以把一个shared_ptr或weak_ptr对象赋给另一个weak_ptr对象。
  w4 = w3;
  return 0;
}

使用weak_ptr解决shared_ptr循环引用问题
循环引用现象
shared_ptr的循环引用,是因为shared_ptr对象虽然被销毁,但其引用计数没有变为0,导致开辟的内存没有被释放:

 

#include<iostream>
#include<string.h>
#include<memory>
#include<stdio.h>
using namespace std;

class A;
class B;

class A
{
    public:
        shared_ptr<B> bb; //解决循环引用:用weak_ptr代替
    public:
        A()
        {
          printf("A()\n");
        }
        ~A()
        {
          printf("~A()\n");
        }
};

class B
{
    public:
        shared_ptr<A> aa; //解决循环引用:用weak_ptr代替
    public:
        B()
        {
            printf("B()\n");
        }
        ~B()
        {
            printf("~B()\n");
        }
}
int main()
{
  shared_ptr<A> a(new A()); //a.use_count: 1
  shared_ptr<B> b(new B()); //b.use_count: 1

  a->bb = b; //b.use_count: 2
  b->aa = a; //a.use_count: 2
  return 0;
}

/*对象a,b生命周期结束时,b先销毁,b count=1,a再销毁,a count=1,于是a,b内部指针指向的内存没有被释放,造成内存泄漏*/

内存空间分析
细究一下上面代码的内存空间情况,首先通过shared_ptr a,b对象开辟了两个内存空间ma,mb以及对应的内部指针pa,pb,然后在pa指向的内存空间中通过b_存放了pb指针和空间mb,在pb指向的内存空间中通过a_存放了pa指针和空间ma,接着a,b对象分别被销毁,引用计数为1,因此指针pa,pb没有被销毁,内存空间ma,mb没有被释放。

可知,如果要解决循环引用的话,需要把其中一块内存空间手动释放,比如:
b->aa.reset();
或者,在智能指针赋值时只设置内部指针,不改变引用计数,也能解决循环引用。这就是weak_ptr的作用了。

weak_ptr解决循环引用
在类成员变量中使用weak_ptr,对象初始化时使用shared_ptr,就能够成功释放开辟的内存:
b->aa = a,a->bb=b没有影响引用计数,因此a,b销毁时,a,b内部指针指向的内存空间也被正常释放了。

标签:对象,weak,C++,引用,shared,ptr,指针
From: https://www.cnblogs.com/lyfily-p-7439305/p/17457288.html

相关文章

  • C++继承
      三类继承方式子类会将父类的所有非静态成员属性继承过来,只不过编译器隐藏了父类的私有属性,子类不可以访问。 1classBase{2public:3inta_;4protected:5intb_;6private:7intc_;8};910classSon:publicBase{11pu......
  • 一个基于C++11的异步安全日志库
    0源码获取gitee1概述这是一个基于c++11的异步日志库目前仅支持windows已通过VS2019+windows11测试。支持自动清理距今指定天数的日志支持设定日志文件输出路径2待实现支持linux3一个范例使用范例 std::unique_ptr<oct_tk::AsyncLogging>async_log=s......
  • C++ 多态原理
    多态就是多种形态,C++的多态分为静态多态与动态多态。动态多态就是通过继承重写基类的虚函数实现的多态,在基类的函数前加上virtual关键字,在派生类中重写该函数,运行时将会根据对象的实际类型来调用相应的函数。多态的总结:(1)用virtual关键字声明的函数叫做虚函数,虚函数肯定是类的......
  • QT的特殊命名空间方式和C++对比
    Qt有以下的写法QT_BEGIN_NAMESPACEnamespaceUi{classWidget;}QT_END_NAMESPACE在开始和结束关键字中间进行命名空间的创建及其内部类的声明 而C++则是直接进行创建namespaceMyNamespace{//在MyNamespace命名空间内定义的类、函数、变量等classMyC......
  • C++ 多态 虚函数virtual
    先解释虚函数,对于基类,子类继承基类后可能会调用其某个函数FA,而不同的子类继承了同一个基类后需要基类内某个同样的函数FA但又不是同个作用,此时则会在对应的子类内对应重载派生出FA_B函数和FA_C函数,而这时要求FA为虚函数(virtual)那为什么不各自写成一个函数B和C呢?这就是多态的意......
  • C++程序开发技巧
    引言类(class)的使用分为两种——基于对象(objectBased)和面向对象(objectoriented)基于对象是指,程序设计中单一的类,和其他类没有任何关系单一的类又分为:不带指针的类(classwithoutpointermembers)和带指针的类(classwithpointermembers)面向对象则是类(class)中涉及了类之间的关......
  • Effective Modern C++(四)再探移动语义与完美转发
    移动语义移动语义是c++11最为重要的特性之一,但这不代表着我们可以在任何时候都无脑地使用它。在以下几个情况下,移动语义并没有什么用处。没有移动操作:要移动的对象没有提供移动操作,所以移动的写法也会变成复制操作。比如对于STL库中的array容器而言,他的元素都直接存储在了......
  • QT--C++简学
    2.1C++语言的新特点(对于C语言来说) 赋值:直接------- intx(100) 在定义的时候就可以赋值,相当于x=100;2.2输入(cin)--------输出(cout)  2.2.1   cout<<x<<endl;  //一个变量             --------printf     cout<<x<......
  • Effective Modern C++(三)引用折叠
    template<typenameT>voidfunc(T&&param);对于一个通用引用,只有当实参被用来实例化通用引用形参时,才会推导形参T。编码机制是简单的。当左值实参被传入时,T被推导为左值引用。当右值被传入时,T被推导为非引用。WidgetwidgetFactory();//返回右值的函数Widgetw;......
  • C++学习资源
    项目STL网站zouxiaohang/TinySTL:TinySTLisasubsetofSTL(cutsomecontainersandalgorithms)andalsoasupersetofSTL(addsomeothercontainersandalgorithms)https://github.com/zouxiaohang/TinySTL......