天天看点

shared_ptr的相关使用

shared_ptr简介

shared_ptr是一个**标准的共享所有权的智能指针。**它允许多个指针指向同一个对象,定义在memory文件内,命名空间为std。

shared_ptr最初实现于Boost库中,后由C++11引入到C++ STL。

shared_ptr利用引用计数的方式实现了对所管理的对象的所有权的分享,即:

  • 允许多个shared_ptr共同管理同一个对象。

shared_ptr是为了解决auto_ptr在对象所有权上的局限性而提出的(auto_ptr是独占的),使用引用计数的机制的同时,提供了可共享所有权的智能指针。这种额外的机制,需要额外的代价:

  • shared_ptr对象除了包括一个所拥有的对象的指针外,还必须包括一个引用计数代理对象的指针。
  • 时间上,开销主要消耗在初始化和拷贝操作上。

shared_ptr的使用

shared_ptr多个指针指向同一个对象,每一个shared_ptr的拷贝都会指向相同的内存。

  • 每使用一次,内部的引用计数就加一;
  • 每析构一次,内部的引用次数就减一;当减为0时,将会自动删除所指向的堆内存。

shared_ptr内部的引用计数是线程安全的,但是对象的读取需要加锁。

  • 初始化。智能指针是一个模板类,可以指定类型,传入指针并通过构造函数初始化。也可以通过make_shared函数初始化。不能将指针直接赋值给一个智能指针,因为一个是类,一个是指针。例如,

    shared_ptr<int> p = new int(1);

    的写法就是错误的。
  • 拷贝与赋值。拷贝操作使得对象的引用计数增加1,赋值操作使得原对象引用计数减一,当计数为0是,自动释放内存。
  • get函数用于获取原始指针。
  • 不能用一个原始指针初始化多个shared_ptr,否则会造成二次释放同一内存。
  • 注意避免循环引用。shared_ptr的一个最大的陷阱就在于循环引用,循环、循环引用将会导致堆内存无法正确释放,从而导致内存泄漏。
#include <iostream>
#include <memory>

int main()
{
	int a = 10;
    std::shared_ptr<int> ptra = std::make_shared<int>(a);
    std::shared_ptr<int> ptra2(ptra); //copy
    std::cout << ptra.use_count() << std::endl;

    int b = 20;
    int *pb = &a;
    //std::shared_ptr<int> ptrb = pb;  //error
    std::shared_ptr<int> ptrb = std::make_shared<int>(b);
    ptra2 = ptrb; //assign
    pb = ptrb.get(); //获取原始指针

    std::cout << ptra.use_count() << std::endl;
    std::cout << ptrb.use_count() << std::endl;
}
           

参考文章:

C++11中智能指针的原理、使用、实现