C++:指针:智能指针

本文介绍了C++中智能指针std::shared_ptr的原理和使用,它通过引用计数自动管理内存,避免内存泄漏。每个std::shared_ptr内部包含指向对象的指针和引用计数,当引用计数为0时自动释放内存。然而,需要注意的是,循环引用可能导致内存无法正确释放,从而引起内存泄漏问题。
摘要由CSDN通过智能技术生成

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 内部原理实例。

// shared_ptr 伪代码

template<typename T>
class Shared_ptr {
    pubolic:
          ........
    private:
          T *_ptr;    // 指针指向的内存区域

          int *_refCount; // 引用次数
}

3:std::weak_ptr 

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

#include<iostream>
#include<vector>
using namespace std;

class ClassB;

class ClassA
{
public:
	ClassA()
	{
		cout << "ClassA Constructor...." << endl;
	}
	~ClassA() 
	{
		cout << "ClassA Destructor....." << endl;
	}
	// 在 A中引用 B
	shared_ptr<ClassB> pb;
};

class ClassB
{
public:
	ClassB() {
		cout << "ClassB Constructor....." << endl;
	}
	~ClassB()
	{
		cout << "ClassB Destructor....." << endl;
	}
	// 在B中引用A
	shared_ptr<ClassA> pa;
};

int main() {
	shared_ptr<ClassA> spa = make_shared<ClassA>();
	shared_ptr<ClassB> spb = make_shared<ClassB>();
	spa->pb = spb;
	spb->pa = spa;
}

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

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

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值