浅谈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只是锁住了转换构造,但是这里是移动构造函数,所以可以使用,有错希望大佬帮忙指正
原文地址:https://www.cnblogs.com/Lis-/p/12639364.html