Contents

C++:智能指针 SmartPointer

本文采用知识共享署名 4.0 国际许可协议进行许可,转载时请注明原文链接,图片在使用时请保留全部内容,可适当缩放并在引用处附上图片所在的文章链接。

简介

智能指针是存储指向动态分类(堆)对象的指针的类,用于生存期控制,确保在离开指针作用域时,自动正确销毁动态分配的对象。
通过引用计数的技术来实现,每使用它一次,内部的引用计数就加1,每析构一次,引用计数减1,减到0时就销毁对象,回收内存。
头文件 #include

分类

三种智能指针:

  • std::shared_ptr  实现共享式拥有,多个指针可以指向相同的对象,该对象和相关资源会在最后一个reference被销毁时释放
  • std::unique_ptr  实现独占式拥有,保证同一时间内只有一个指针可以指向该对象
  • std::weak_ptr   持有被shared_ptr所管理对象的引用,但是不会改变引用计数值。允许共享但不拥有某对象 另一方面,auto_ptr已经被废弃,C98,之前和std::unique_ptr一个意思

shared_ptr

创建智能指针时必须提供额外的信息,指针可以指向的类型:

1
2
shared_ptr<string> p1;
shared_ptr<list<int>> p2;

智能指针检查

1
2
if(p1  && p1->empty())
    *p1 = "hi";

shared_ptr和unique_ptr都支持的操作

image/shared_ptr和unique_ptr都支持的操作.png

shared_ptr特有的操作

image/shared_ptr特有的操作.png

make_shared函数:最安全的分配和使用动态内存的方法就是调用一个名为make_shared的标准库函数,此函数在动态内存中分配一个对象并初始化它,返回指向此对象的shared_ptr。头文件和share_ptr相同,在memory中。

1
2
3
shared_ptr<int> p3 = make_shared<int>(42);
shared_ptr<string> p4 = make_shared<string>(10,'9');
shared_ptr<int> p5 = make_shared<int>();

shared_ptr的拷贝和赋值
可以认为每个shared_ptr都有一个关联的计数器,通常称其为引用计数,无论何时我们拷贝一个shared_ptr,计数器都会递增。当我们给shared_ptr赋予一个新值或是shared_ptr被销毁(例如一个局部的shared_ptr离开其作用域)时,计数器就会递减,一旦一个shared_ptr的计数器变为0,它就会自动释放自己所管理的对象。

1
2
3
4
5
auto r = make_shared<int>(42);//r指向的int只有一个引用者
r=q;//给r赋值,令它指向另一个地址
    //递增q指向的对象的引用计数
    //递减r原来指向的对象的引用计数
    //r原来指向的对象已没有引用者,会自动释放

定义和改变shared_ptr的其他方法

unique_ptr

某个时刻只能有一个unique_ptr指向一个给定对象,由于一个unique_ptr拥有它指向的对象,因此unique_ptr不支持普通的拷贝或赋值操作。
unique的操作

## weak_ptr weak_ptr是一种不控制所指向对象生存期的智能指针,它指向一个由shared_ptr管理的对象,将一个weak_ptr绑定到一个shared_ptr不会改变shared_ptr的引用计数。一旦最后一个指向对象的shared_ptr被销毁,对象就会被释放,即使有weak_ptr指向对象,对象还是会被释放。
由于对象可能不存在,我们不能使用weak_ptr直接访问对象,而必须调用lock,此函数检查weak_ptr指向的对象是否存在。如果存在,lock返回一个指向共享对象的shared_ptr,如果不存在,lock将返回一个空指针。 ## scoped_ptr scoped和weak_ptr的区别就是,给出了拷贝和赋值操作的声明并没有给出具体实现,并且将这两个操作定义成私有的,这样就保证scoped_ptr不能使用拷贝来构造新的对象也不能执行赋值操作,更加安全,但有了”++”“–”以及“*”“->”这些操作,比weak_ptr能实现更多功能。

智能指针父类和子类的转化