【C++】智能指针

2023-12-14 19:25:19

智能指针

文章目录

  • 智能指针
    • 智能指针介绍
    • unique_ptr
    • shared_ptr
    • weak_ptr

智能指针介绍

智能指针可以帮助C++程序员管理动态分配的内存的,它会帮助我们自动释放new出来的内存,从而避免内存泄漏!
智能指针不是指针,是一个管理指针的类,用来存储指向动态分配对象的指针,负责自动释放动态分配的对象,防止堆内存泄漏。
动态分配的资源,交给一个类对象去管理,当类对象声明周期结束时,自动调用析构函数释放资源

C++11后auto_ptr 已经被“抛弃”,改为unique_ptr替代!C++11后不建议使用auto_ptr,因此本位不从unique_ptr开始介绍

  • 头文件
#include<memory>
  • 创建

同模板类

unique_ptr<string> p1(new string("hello"));
shared_ptr<int>p2(new int(5));

API:

  • get()获取智能指针托管的指针地址
unique_ptr<string> p1(new string("hello"));
cout << p1.get() << endl;
//0x55fade17eeb0
  • release() 取消智能指针对动态内存的托管
unique_ptr<int>p1(new int(5));
int*pp = p1.release();
delete pp;//因为智能指针内部源码使用new所以这里可用delete

unique_ptr

两个指针不能指向同一个资源,复制或赋值都会改变资源的所有权。

无法进行左值unique_ptr复制构造,也无法进行左值复制赋值操作,但允许临时右值赋值构造和赋值
保存指向某个对象的指针,当它本身离开作用域时会自动释放它指向的对象。

unique_ptr<int>p1(new int(5));
unique_ptr<int>p2(new int(6));
// p1 = p2; //禁止
// unique_ptr<int> p3(p1);//禁止
unique_ptr<int> p3(move(p1)); //move可以
p1 = move(p2);
  • STL使用
vector<unique_ptr<int>> v;
unique_ptr<int> ptr1 (new int (5));
v.push_back(move(ptr1));
  • 数组使用
nique_ptr<int[]> array(new int[5]);

shared_ptr

shared_ptr记录引用特定内存对象的智能指针数量,当复制或拷贝时,引用计数加1,当智能指针析构时,引用计数减1,如果计数为零,代表已经没有指针指向这块内存,就释放它

shared_ptr<int>p1(new int(5));
shared_ptr<int>p2(new int(6));
shared_ptr<int>p3(p1);
//使用make_shared 初始化对象,分配内存效率更高
//make_shared函数的主要功能是在动态内存中分配一个对象并初始化它,返回指向此对象的shared_ptr
shared_ptr<int> p4 = make_shared<int>(7);
cout << *p3; //5
p3 = p2;
cout << *p3; //6
  • use_count()可以获得当前托管指针的引用计数
cout << p3.use_count(); //2
  • 循环引用问题
struct Father{
    shared_ptr<Son> son_;
};

struct Son{
    shared_ptr<Father> father_;
};

int main()
{
    auto father = make_shared<Father>();
    auto son = make_shared<Son>();

    father->son_ = son;
    son->father_ = father;

    return 0;
}

互相持有导致循环引用问题,析构函数不能正常使用

weak_ptr

weak_ptr 设计的目的是为配合 shared_ptr 而引入的一种智能指针来协助 shared_ptr 工作, 它只可以从一个 shared_ptr 或另一个 weak_ptr 对象构造, 它的构造和析构不会引起引用记数的增加或减少。 同时weak_ptr 没有重载*和->但可以使用 lock 获得一个可用的 shared_ptr 对象。

shared_ptr<int>p1(new int(5));
weak_ptr<int>p2(p1);
cout << p1.use_count() << endl; //1
cout << p2.use_count() << endl; //1
cout << *p2 << endl; //错误
  • 使用 lock 获得一个可用的 shared_ptr 对象
weak_ptr<int>p2(p1);
shared_ptr<int>p3 = p2.lock();
  • weak_ptr解决循环引用问题
struct Father{
    shared_ptr<Son> son_;
};

struct Son{
    weak_ptr<Father> father_;
};

int main()
{
    auto father = make_shared<Father>();
    auto son = make_shared<Son>();

    father->son_ = son;
    son->father_ = father;

    return 0;
}

我们在会产生循环引用的位置,把shared_ptr换成weak_ptr。它不参与资源的管理,他是专门用来解决引用计数的,我们可以使用一个shared_ptr 来初始化一个weak_ptr,但是weak_ptr 不增加引用计数,不参与管理,但是也像指针一样访问修改资源。


参考资料1
参考资料2

文章来源:https://blog.csdn.net/qq_60755751/article/details/134875745
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。