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

    1、智能指针概述

    智能指针本身是个类,程序员在为指针进行内存分配后,可能忘记使用delete销毁内存,为了避免这个问题,出现了智能指针。智能指针在创建时调用构造函数,在消亡时(超出使用范围以后)自动调用析构函数,这样就起到一个内存回收的作用。智能指针的对象都是栈上创建。

    2、四种智能指针讲解

    2.1 std::auto_ptr

    std::auto_ptr属于C++98方案,C++11已经弃用。不支持复制(拷贝构造函数)和赋值(operator =),但进行该操作时编译器不会报错。该指针采用所有权模式,假设有std::auto_ptr p1和p2,此时p1已经初始化,将p1赋值给p2,则p2剥夺了p1的所有权,当程序运行时访问p1会报错,因为此时p1所指位置并不确定,因此存在潜在内存问题。

    2.2 std::unique_ptr

    std::unique_ptr是C++11中新增的用来替代auto_ptr的智能指针。std::unique_ptr实现独占式拥有或严格拥有概念,保证同一时间内只有一个只能指针可以指向该对象,同时智能指针本身是一个类,在对象生命周期结束以后会自动调用析构函数释放内存,从而避免了内存泄漏问题。那么刚才说的有关std::auto_ptr出现的情况如果用std::unique_ptr替换则无法通过编译,需要赋值时调用std::move方法。

    2.3 std::shared_ptr

    std::shared_ptr实现共享式拥有,多个智能指针可以指向一个相同对象,该对象和其相关资源会在最后一个引用被销毁时释放。std::shared_ptr是为了解决std::auto_ptr在对象所有权上的局限性,在使用引用计数的机制上提供了可以共享所有权的智能指针。

    2.4 std::weak_ptr

    std::weak_ptr是一中不控制对象生命周期的智能指针,属于弱引用。它指向一个std::shared_ptr管理的对象,其设计的目的是为了配合std::shared_ptr的使用,它只能从一个std::shared_ptr或另一个std::weak_ptr对象构造,其构造和析构不会引起引用计数的增加或减少。std::weak_ptr是用来解决std::shared_ptr相互引用时的死锁问题(如果两个std::shared_ptr相互引用,那么这两个指针的引用计数永远不可能降到0,资源永远不能释放)。

    3、手写实现std::shared_ptr

    #include <memory>
    #include <iostream> ​ template <typename T> class MySharedPtr { private: T *_ptr; size_t *_reference_count;
    // 引用计数操作 void __releaseCount() { if(_ptr) { (*_reference_count)--; if(*_reference_count == 0) { delete _ptr; delete _reference_count; } } } ​ public: // 构造函数 MySharedPtr(T *p = nullptr): _ptr(p), _reference_count(new size_t) { if(p) *_reference_count = 1; else *_reference_count = 0; } // 复制构造函数 MySharedPtr(const MySharedPtr &s_p) { if(this != &s_p) { _ptr = s_p._ptr; _reference_count = s_p._reference_count; (*_reference_count)++; } } // 析构函数 ~MySharedPtr() { if(--(*_reference_count) == 0) { delete _ptr; delete _reference_count; } } // 赋值操作符重载 MySharedPtr& operator=(const MySharedPtr &s_p) { if(_ptr == s_p._ptr) return *this; __releaseCount(); _ptr = s_p._ptr; _reference_count = s_p._reference_count; (*_reference_count)++; return *this; } // ->操作符重载 T* operator->() { if(_ptr) return _ptr; } // 指针取值操作符重载 T& operator*() { if(_ptr) return *_ptr; } };

    // test
    int main()
    {
        int a = 10;
        int *p1 = &a;
        MySharedPtr<int> p2 = p1;
        std::cout << *p2 << std::endl;

        return 0;
    }
     
  • 相关阅读:
    奇异值分解(SVD)与在降维中的应用
    拉格朗日乘子法&KKT条件
    有监督学习、无监督学习、半监督学习
    LSTM学习—Long Short Term Memory networks
    Ubuntu16.04+CUDA8.0+cuDNN5.1+Python2.7+TensorFlow1.2.0环境搭建
    激活函数
    C基础学习笔记
    Hive
    Fragment跳转至Activity片段随笔
    冒泡排序和选择排序
  • 原文地址:https://www.cnblogs.com/horacle/p/14578125.html
Copyright © 2011-2022 走看看