C++之动态内存以及智能指针

1.动态内存

  • 定义:new在动态内存中为对象分配空间并返回一个指向该对象的指针,我们可以选择对对象进行初始化;delete接受一个动态对象的指针销毁该对象,并释放与之关联的内存。
  • 存在的问题:当多次释放动态分配的内存时,导致引用非法内存的指针;当忘记释放动态分配的内存时,会导致内存泄露。
  • 智能指针本质:避免悬空指针的产生。

2.shared_ptr类

2.1 shared_ptr意义

  • 意义:shared_ptr实现共享式拥有,多个智能指针可以指向相同对象,使用计数机制来表明资源被几个指针共享,该对象和其相关资源会在最后一个引用被销毁时候释放。同时因为智能指针是一个类,当超出对象的作用域时,会自动调用对象的析构函数,释放相关资源。所以智能指针的作用原理就是在函数结束时自动释放内存空间

2.2 shared_ptr定义和初始化

  • 智能指针和普通指针区别:对shared_ptr进行初始化时不能将一个普通指针直接赋值给智能指针,因为普通指针是指针,智能指针是类,类型不一致。可以通过make_shared函数或者通过构造函数传入普通指针,并且可以通过get函数获得普通指针
  • shared_ptr定义及初始化:调用make_shared的标准库函数
//使用make_shared函数进行定义及初始化时,
//make_shared一次性为int对象和用于引用计数的数据都分配了内存;
//而new操作符只是为int分配了内存;

//指向一个值为42的int的shared_ptr;
shared_ptr<int> p1 = make_shared<int>(42);

//指向一个值为“9999999999”的string;
shared_prt<string> p2 = make_shared<string>(10,'9');

//指向一个值初始化的int,即值为0;
shared_prt<int> p3 = make_shared<int>();

//同时我们可以用auto定义一个对象来保存make_shared的结果;
 auto p4 = make_shared<vector<string>>();

//使用原始指针创建shared_ptr对象;
shared_ptr<Person> p(new Person());

//上面这行代码在堆上创建了两块内存:1:存储int,
//2:用于引用计数的内存,管理附加此内存的shared_ptr对象的计数,最初计数将为1;

2.3 shared_ptr的use_count成员函数

  • 引用计数user_countint count = p.user_count();。智能指针类能记录有多少个shared_ptr 指向相同的对象,并能在恰当的时候自动释放对象。
  • 关联的计数器(引用计数)递增一的情况:可以和调用拷贝构造函数类比。
    a.用一个shared_ptr初始化另一个shared_ptr;
    b.shared_ptr作为参数传递给一个函数 ;
    c.shared_ptr作为函数的返回值。
  • 关联的计数器(引用计数)递减一的情况
    a.给shared_ptr赋值一个新值 (operator= 或 reset() 赋值);
    b.shared_ptr被销毁(例如局部的shared_ptr离开其作用域)。同时如果一个shared_ptr的计数器变为0,就会释放自己所管理的对象。例如:
//r指向的int只有一个引用者;
auto r = make_shared<int>(42);

r = q;//给r赋值,令他指向另一个地址。
	  //递增q指向的对象的引用计数,
	  //符合use_count减一的第1种情况,递减r指向的对象的引用计数,
	  //r原来指向的对象已没有引用者,会自动释放;

2.4 shared_ptr拷贝和赋值

  • 当进行拷贝和赋值操作时,每个shared_ptr都会记录有多少个shared_ptr 指向相同的对象。例如,
    auto p = make_shared<int>(42);//p指向的对象只有p一个引用者;
    auto q(p);//或者auto q=p; p和q指向相同的对象,此对象有两个引用者;

2.5 shared_ptr删除

  • 分离关联的原始指针:要使 shared_ptr 对象取消与相关指针的关联,可以使用reset()函数:
  • 不带参数的reset()p1.reset();,它将引用计数减少1,如果引用计数变为0则删除指针。
  • 带参数的reset()p1.reset(new int(34));,在这种情况下,它将在内部指向新指针,因此其引用计数将再次变为1。
  • 使用nullptr重置p1 = nullptr;
  • 自定义删除器deleter:有些时候在析构函数中,delete函数并不能满足我们的需求,可能还想加其他的处理。例如:当 shared_ptr 对象指向数组shared_ptr<int> p(new int[12]);,像这样申请的数组,应该调用delete []释放内存,而shared_ptr析构函数中默认delete并不能满足需求。因此需要给shared_ptr添加自定义删除器,这种情况下可以将回调函数传递给shared_ptr 的构造函数,该构造函数将从析构函数中调用以进行删除。即
// 自定义删除器
void del(Person *x){
   
	cout << "DELETER FUNCTION CALLED\n";
	delete[] x;
}
// 构造函数传递自定义删除器指针
shared_ptr<Person> p(new Person[12], del);
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值