首页 > 编程语言 >Modern C++ 智能指针 shared_ptr

Modern C++ 智能指针 shared_ptr

时间:2022-10-27 21:34:14浏览次数:47  
标签:std auto Modern C++ 智能 shared ptr 指针

现代C++为了解决内存泄露以及资源回收等问题,引入了智能指针的概念。在日常的C++实践中也是高频使用。
本文是在实践过程中,对现代C++中的智能指针进行的一个稍微全面的总结。

概念及使用

std::shared_ptr也即智能指针,采用RAII手法,是一个模版对象。std::shared_ptr表示某一个资源的共享所有权。

可以通过如下两种方式创建std::shared_ptr对象

auto p = shared_ptr<T>(new T);
auto p = make_shared<T>(T{});

实现原理

此处以如下代码为例,讲解std::shared_ptr的实现原理(仅给出便于理解的感性认知,源码层面的讲解不在本文范围之内).

#include <iostream>
#include <memory>
using std::cout;


int main() {
  auto p = std::make_shared<int>(4);
  auto p1 = std::shared_ptr<int>(new int(4));
  cout << *p << *p1 << "\n";
  return 0;
}

上述对象p的内存布局如下所示

关于上述实现原理图,需要作如下说明

  • std::shared_ptr本身只包含两个对象:指向控制块对象的Ctr指针和一个指向其管理的资源的指针Ptr
  • 当采用std::shared_ptr(new T{})这种形式创建智能指针时,其控制块对象中会包含一个M_ptr成员,该指针指向智能指针所管理的资源
  • 控制块对象至少会包含use_count(引用计数), weak_count(弱引用计数), 以及其他数据这三部分内容

再来看看,针对对象p1的内存布局

关于上述实现原理图,需要作如下说明

  • 当采用std::make_shared创建智能指针时,其控制块对象和被管理资源被存放在同一个内存块中
  • 当采用std::make_shared创建智能指针时,其控制块对象中,不会包含M_ptr成员(该成员指向智能指针所管理的资源)

NOTE:建议优先考虑std::make_shared方式创建shared_ptr对象

使用场景

本小节主要讲解shared_ptr的几种使用场景包括可能存在的问题。

拷贝和移动

此处探讨shared_ptr 的拷贝和移动时,其引用计数的变化。

此处通过如下代码讲解

#include <iostream>
#include <memory>

int main() {
    auto p = std::make_shared<int>(4);
    auto p1 = p;
    std::cout << "p use_count: " << p.use_count() << "\n";
    auto p2 = std::move(p);
    std::cout << "p1 use_count: " << p1.use_count() << "\n";
    std::cout << "p use_count: " << p.use_count() << "\n";

    return 0;
}

上述输出结果为

p use_count: 2
p1 use_count: 2
p use_count: 0

关于上述原因:

shared_ptr的拷贝构造函数会增加引用计数,使用move()移动语义将左值转换为右值,调用shared_ptr的移动构造函数,移动构造函数是一个浅拷贝的操作,不会增加引用计数。
并且使用move()一个shared_ptr是移动而不是复制,可以避免增加数量再减少数量的两个原子操作,可以节省相对耗时的原子操作。
NOTE:如果非必要建议使用移动构造shared_ptr

Guideline: Don’t pass a smart pointer as a function parameter unless you want to use or manipulate the smart pointer itself, such as to share or transfer ownership.

Guideline: Express that a function will store and share ownership of a heap object using a by-value shared_ptr parameter.

Guideline: Use a non-const shared_ptr& parameter only to modify the shared_ptr. Use a const shared_ptr& as a parameter only if you’re not sure whether or not you’ll take a copy and share ownership; otherwise use widget* instead (or if not nullable, a widget&).

除非您要使用或操纵智能指针本身,例如共享或转让所有权,否则不要将智能指针作为函数参数传递。准则:表示函数将使用按值shared_ptr参数存储和共享堆对象的所有权。准则:仅使用非常量shared_ptr&参数来修改shared_ptr。仅在不确定是否要复制并共享所有权时,才使用const shared_ptr&作为参数。否则,请改用widget *(或者,如果不能为null,则使用widget&)。

标签:std,auto,Modern,C++,智能,shared,ptr,指针
From: https://www.cnblogs.com/happinesspills/p/16831524.html

相关文章