上片博客为大家简单介绍了C++中开辟动态内存的方法,虽然动态内存有好多优点,但是如果我们使用不好的话有时候会给我们的程序带来灾难性的后果,今天这篇博客就为大家介绍一种安全的使用指针的方式智能指针
1.智能指针的介绍
新标准库为我们提供了俩种智能指针。智能指针的使用方法和常规指针基本相似,重要的区别是智能指针能够在恰当的时机自动释放它所指向的对象所占用的空间,而不需要我们人为的区释放,这一点能够使我们写出来的程序更安全。新标准提供了俩中智能指针,分别是shared_ptr和unique_ptr,此俩中指针都定义在头文件memory中
2.shared_ptr类
智能指针说白了就是把普通指针封装进一个类里,我们利用类对象的天然特性来对指针的释放进行精确的控制,而shared_ptr就是通过一个引用计数来知道当前有多少个指针共用同一个内存空间,当引用计数变为0,则意味这此内存空间不再有对象使用,则其会在自身的析构函数中将此块内存释放掉
1.shared_ptr的定义
智能指针是一个模板类,所以在创建智能指针时一定要先实例化(就是给指针一个类型)
具体方式如下
shared_ptr<int> p;//p可以指向int类型
shared_ptr<vector<int>> p; //p可以指向int类型的vector
默认初始化的指针指针中所保存的真实指针是个空指针
2.shared_ptr所支持的操作
下表列出了shared_ptr类所支持的操作
操作 | 说明 |
---|---|
shared_ptr p | p为指向T类型的空指针 |
p->mem | 获得智能指针指向的对象 |
p.get() | 获得智能指针所保存的源指针 |
make_shared(args) | 返回一个shared_ptr,指向一个动态分配类型为T的对象,使用args初始化此对象 |
p.unique() | 若p.use_count()为1,返回true,否则返回false |
p.use_count() | 返回与p共享对象的智能指针数量,主要用于调试 |
以上表格需重点说明的有如下俩点
(1)由于智能指针重载了指针运算符->所以我们可以直接用p->mem类访问源指针中的成员
(2)make_shared是最安全分配和使用动态内存的方法,其也定义在memory中,当要用make_shared时,必须指定想要创建对象的类型,定义方式与模板类相同
以下给出了make_shared的实例
//指向一个值为66的int型的shared_ptr
shared_ptr<int> p1 = make_shared<int>(66);
//默认初始化为0
shared_ptr<int> p2 = make_shared<int>();
3.shared_ptr的拷贝与赋值对引用计数的影响
每个shared_ptr都有一个引用计数,用来记录当前有多少和shared_ptr对象在使用同一个指针,当引用计数变为0时,则意味着没有对象在使用该指针,则shared_ptr就会通过析构函数将该地址指向的内存空间释放掉
拷贝和赋值都会使所关联的智能指针的引用计数加1
事例如下
此时shared_ptr的引用计数为1
auto p1 = make_shared<int>(5);
{
//shared_ptr的引用计数为3
auto p2 = p1;
auto p3(p1);
//作用域结束p2和p3的这俩个shared_ptr<int>类型的对象被释放掉了,引用计数变为1,由于还未变为0,所以p1中保存的指针还不会被释放
}
4.shared_ptr与new结合使用
如果我们不初始化一个智能指针,那么它默认是初始化为一个空指针,其实我们还可以用new返回的指针来初始化智能指针
shared_ptr<int> p(new int(7));
5shared_ptr的注意事项
(1)由于智能指针类构造函数不支持强制类型转换,所以不能将一个普通指针赋给智能指针
(2)智能指针可以调用get()函数获得它所封装的源指针,但是千万不要用get()函数获得源指针后将其delete掉,否则有可能造成出错