zoukankan      html  css  js  c++  java
  • 浅谈C++智能指针

    操作内存

    创建内存:new

    过程:用new创建内存,如果成功的话那么直接分配,然后调用对象的构造函数,如果分配不够,那么先去调用用户自己写的set_new_handler函数,一般这个函数是用来释放些内存,然后使多点内存,然后再去申请,如果还是不行,再调用该函数,但是一般就是用个标记变量释放第一次,第二次直接退出,然后会返回一个bad_alloc错误

    释放内存:delete

    过程:调用析构函数,然后释放内存,如果释放一个数组,那么就是找到数组前几个字节,一般有个保存长度的东西

    智能指针

    原因:因为动态内存在用指针使用上,如果忘记释放,那么很容易造成内存泄漏,所以推出了智能指针,智能指针也就是一个利用了rall资源管理机制,就是利用把当前变量转换成对象,利用析构函数来释放内存

    shared_ptr<>:首先我们要清楚的是这是一个对象,也就是包括了构造 析构 赋值 等的一个东西,这个话是一个能允许多个指针来操作的一个指针

    核心概念:类里面包含一个计数器,一个指针,通过拷贝构造,赋值 来使当前计数器加一,如果释放计数器减一,计数器为0才使用delete,改变指向的时候,就要先把老对象计数器减一,然后再去改变指向再计数器加一

    初始化:开始利用构造函数进行初始化,如果在外面的话就需要使用make_shared<T>(x)来把当前给转化成智能指针对象

    unique_ptr<int> :也就是只能一个指针指向对象,所以就需要把拷贝构造和赋值操作都给禁用掉

     主要问题:

    u.release 不能直接普通的调用,这个只是放弃控制权而已,但是这个又是只有一个指针指向,如果不把返回值给其他对象那么就会找出内存泄漏

    正确操作 u1.reset(u2.release)

    shared_ptr的循环引用问题

    class B;
    class A
    {
    public:
      shared_ptr<B> m_b;
    };
     
    class B
    {
    public:
      shared_ptr<A> m_a;
    };
     
    int main()
    {
      while (true)
      {
        shared_ptr<A> a(new A); //new出来的A的引用计数此时为1
        shared_ptr<B> b(new B); //new出来的B的引用计数此时为1
        a->m_b = b; //B的引用计数增加为2
        b->m_a = a; //A的引用计数增加为2
      }
     
      //b先出作用域,B的引用计数减少为1,不为0,所以堆上的B空间没有被释放,且B持有的A也没有机会被析构,A的引用计数也完全没减少
     
      //a后出作用域,同理A的引用计数减少为1,不为0,所以堆上A的空间也没有被释放
     
    }

    导致结果:导致智能指针指向的内存空间没有释放,造成内存泄漏

    导致原因:如果退出循环,那么肯定是b先析构掉,那么b指向的内存空间就会引用计数-1,但是不是零,A有成员指向了它,所以不释放内存空间,不释放内存空间的话,那么他的成员指向A也还存在,所以

    A也因为相同的原因不能够释放掉

    解决方法:把类中的shared_ptr替换成weak_ptr,这个东西就是为了解决循环引用而发明的,他的话是利用不算计数,里面指向的时候不会算计数,那么也不存在循环引用的问题了,但是因为weak_ptr指向的空间有可能是一个已经被释放掉的,所以需要判断是不是已经释放掉再去使用

    指针转换

    智能指针的赋值转换构造是explicit的,所以不能隐式转换

    指针转智能指针

    int *p=new int(3);
    shared_ptr<int> q(p);
    
    shared_ptr<int> q=make_shared<int>(3);

    unique_ptr转shared_ptr

    shared_ptr<int> q = make_unique<int>(3);
    
    
    unique_ptr<int> p = make_unique<int>(3;
    shared_ptr<int> q;
    q=move(p);//以我的理解是,explicit只是锁住了转换构造,但是这里是移动构造函数,所以可以使用,有错希望大佬帮忙指正
  • 相关阅读:
    LED事件
    CSR8670按钮事件
    编译提示:warning: ISO C89 forbids mixed declarations and code
    C#使用Smtp,通过qqmail发送邮件
    编写VS的Snippet
    WPF的Clipboard.SetText()有问题
    HttpListenerRequest.ContentEncoding
    jQuery的Deferred对象教程
    visual studio如何修改c++项目的.net framework框架版本
    如何让Sqlite支持Entity Framework Code-First
  • 原文地址:https://www.cnblogs.com/Lis-/p/12639364.html
Copyright © 2011-2022 走看看