• C++:指针:智能指针


    1:引用计数:

    1.         引用计数是为了防止内存泄漏而产生的一种方法,其基本思想是对于动态分配的对象,进行引用计数,每当增加一次对对象的引用,那么引用对象的引用计数就正价一次,每删除一次引用,引用计数就会减一次,当一个引用对象的引用计数为零时,就会自动删除指向的堆内存。
    2.         在传统C++编程中,需要手动释放资源来避免忘记释放资源带来的资源泄漏,这是通过 new和delete实现的,C++11中通过引入智能指针的概念,使用了引入计数的想法,使得程序员不需要关心手动释放内存,这些智能指针包括 : std::shared_prt,std::unique_ptr,std::weak_ptr 。使用他们需要包含头文件。

    unique_ptr , shared_ptr,weak_ptr 。

    2:std::shared_ptr

    2.1 原理简介

    std::shared_ptr是C++ 提供的最常用的智能指针,采用引用计数,多个shared_ptr中的 T *ptr指向同一个内存区域(同一个对象),并且他们(多个shared_ptr)共同维护一个引用计数器,记录着同一个实例被引用的次数,当引用次数大于0时内存可用,等于0时释放内存。实现了任何地方都不是使用时自动删除指针,帮助解决消除内存泄漏和悬空指针的问题。

    2.2 :底层原理解析

    每个std::shared_ptr指针在内部维护着两个内存位置:

    1. 指向对象的指针
    2. 用于控制引用计数数据的指针
    • 当新的 shared_ptr对象与指针关联时,则在其构造函数中,将与此指针关联的引用计数增加1。
    • 当任何 shared_ptr对象超出作用域时,则在析构函数中,将与此指针关联的引用计数减1。
    • 如果最终引用计数为0,就表示没有其他任何 shared_ptr对象与此内存关联,那么在这种情况下,shared_ptr就会自动调用 delete函数删除内存,不需要程序员自己处理,完美的解决了内存泄漏的隐患
    • 注意:shared_ptr最大的一个陷阱就是循环引用的问题,循环引用会倒追内存无法正常正确的被释放,从而导致内存泄漏。

    下面是 shared_ptr 内部原理实例。

    1. // shared_ptr 伪代码
    2. template<typename T>
    3. class Shared_ptr {
    4. pubolic:
    5. ........
    6. private:
    7. T *_ptr; // 指针指向的内存区域
    8. int *_refCount; // 引用次数
    9. }

    3:std::weak_ptr 

    案例:shared_ptr 带来的循环引用问题

    1. #include
    2. #include
    3. using namespace std;
    4. class ClassB;
    5. class ClassA
    6. {
    7. public:
    8. ClassA()
    9. {
    10. cout << "ClassA Constructor...." << endl;
    11. }
    12. ~ClassA()
    13. {
    14. cout << "ClassA Destructor....." << endl;
    15. }
    16. // 在 A中引用 B
    17. shared_ptr pb;
    18. };
    19. class ClassB
    20. {
    21. public:
    22. ClassB() {
    23. cout << "ClassB Constructor....." << endl;
    24. }
    25. ~ClassB()
    26. {
    27. cout << "ClassB Destructor....." << endl;
    28. }
    29. // 在B中引用A
    30. shared_ptr pa;
    31. };
    32. int main() {
    33. shared_ptr spa = make_shared();
    34. shared_ptr spb = make_shared();
    35. spa->pb = spb;
    36. spb->pa = spa;
    37. }

      在上面代码中,ClassA和ClassB之间存在着循环引用,从运行结果可以看到:当main函数运行结束后,spa和spb管理的动态资源并没有得到释放,产生了内存泄漏。

    所以为了解决类似这样的问题,C++11引入了 weak_ptr ,来打破这种循环引用。

     

     

     

     

  • 相关阅读:
    STM32学习笔记一:开发环境
    2023最新SSM计算机毕业设计选题大全(附源码+LW)之java高校教学过程管理系统34085
    Spring中@Valid和@Validated有哪些不同呢?
    不了解无线调制方式?这几个“老古董”大家现在还在用!
    (4) OpenCV图像处理kNN近邻算法-识别数字0和1
    倍市得CEM-ISV合作共创:体验加持,共建数字化产品护城河
    共享主机安全吗(以及如何保护它)?
    Android NDK篇-C++ 自定义命名空间与拷贝构造函数
    快人一步!利用LLM实现数据处理自动化
    如何用BigDecimal定义数字
  • 原文地址:https://blog.csdn.net/u013620306/article/details/128015046