本章所有内容均从C++ Primer摘录总结
1.为什么使用make_shared?

make_shared函数的主要功能是在动态内存中分配一个对象并初始化它,返回指向此对象的shared_ptr;由于是通过shared_ptr管理内存,因此一种安全分配和使用动态内存的方法。

如下为make_shared的使用:

//p1指向一个值为"9999999999"的string
shared_ptr<string> p1 = make_shared<string>(10, '9');  shared_ptr<string> p2 = make_shared<string>("hello");  shared_ptr<string> p3 = make_shared<string>(); 

从上述例子我们可以看出以下几点:
  1)make_shared是一个模板函数;
  2)make_shared模板的使用需要以“显示模板实参”的方式使用,如上题所示make_shared<string>(10, 9),如果不传递显示 模板实参string类型,make_shared无法从(10, '9')两个模板参数中推断出其创建对象类型。
  3)make_shared在传递参数格式是可变的,参数传递为生成类型的构造函数参数,因此在创建shared_ptr<T>对象的过程中调用了类型T的某一个构造函数。

2.make_shared模板实现
  如下为make_shared的库函数实现版本:

template<typename _Tp, typename... _Args>
inline shared_ptr<_Tp>
make_shared(_Args&&... __args)
{typedef typename std::remove_const<_Tp>::type _Tp_nc;return std::allocate_shared<_Tp>(std::allocator<_Tp_nc>(),std::forward<_Args>(__args)...);
}template<typename _Tp, typename _Alloc, typename... _Args>
inline shared_ptr<_Tp>
allocate_shared(const _Alloc& __a, _Args&&... __args)
{return shared_ptr<_Tp>(_Sp_make_shared_tag(), __a,std::forward<_Args>(__args)...);
}

我们依次分析上述的关键代码

//关键行1
template<typename _Tp, typename... _Args>
inline shared_ptr<_Tp> make_shared(_Args&&... __args)  //关键行2
std::forward<_Args>(__args)...//关键行3
return shared_ptr<_Tp>(_Sp_make_shared_tag(), __a,std::forward<_Args>(__args)...);

从上述关键代码可以看出: make_shared是组合使用可变参数模板与forward(转发)机制实现将实参保持不变地传递给其他函数。如最开始的string例子
1) 使用可变参数:是因为string有多个构造函数,且参数各不相同;

2)Args参数为右值引用(Args&&)和std::forward:是为了保持实参中类型信息的传递。这样当传递一个右值string&& 对象给make_shared时,就可以使用string的移动构造函数进行初始化。注意,两者必须结合使 用,缺一不可;

此外std::forward<_Args>(__args)...是采用 包扩展形式调用的,原理如下:

shared_ptr<string> p1 = make_shared<string>(10, '9'); //扩展如下,对两个参数分别调用std::forward
return shared_ptr<string>(_Sp_make_shared_tag(), _a ,std::forward<int>(10),  std::forward<char>(c));

补充说明:
①模板参数为右值引用,采用引用折叠原理:

 1)参数为左值时,实参类型为普通的左值引用; T& &, T&& &,T& && =>T&2)参数为右值时,实参类型为右值: T&& && => T&&

std::forward:是一个模板,通过显示模板实参来调用,调用后forward返回显示实参类型的右值引用。即,forward<T>的返回类型为T&&,在根据上述引用折叠原理即可保存参数是左值还是右值类型;比如:

int i = 0;
std::forward<int>(i), i将以int&传递
std::forward<int>(42), 42将以int&&传递

std::forward实现代码:

/**
*  @brief  Forward an lvalue.
*  @return The parameter cast to the specified type.
*
*  This function is used to implement "perfect forwarding".
*/
template<typename _Tp>
constexpr _Tp&&
forward(typename std::remove_reference<_Tp>::type& __t) noexcept
{ return static_cast<_Tp&&>(__t); }/**
*  @brief  Forward an rvalue.
*  @return The parameter cast to the specified type.
*
*  This function is used to implement "perfect forwarding".
*/
template<typename _Tp>
constexpr _Tp&&
forward(typename std::remove_reference<_Tp>::type&& __t) noexcept
{static_assert(!std::is_lvalue_reference<_Tp>::value, "template argument"" substituting _Tp is an lvalue reference type");return static_cast<_Tp&&>(__t);
} 

make_shared理解相关推荐

  1. C++ 智能指针std::shared_ptr简单使用和理解

    参考:https://blog.csdn.net/u011068702/article/details/83692838 1  智能指针std::shared_ptr相关知识和如何使用 我们这里先说下 ...

  2. 深入理解C++内存管理

    深入理解C++内存管理 一文了解所有C++内存的问题 AlexCool 目录 一  C++内存模型 二  C++对象内存模型 三 C++程序运行内存空间模型 四  C++栈内存空间模型 五 C++堆内 ...

  3. 看完这个你还不理解右值引用和移动构造 你就可以来咬我(下)

    共分三篇,这是第3篇.另外两篇,看完这个你还不理解右值引用和移动构造 你就可以来咬我(上),看完这个你还不理解右值引用和移动构造 你就可以来咬我(中). 下面是新标准下的其他特性(共十点),了解一下, ...

  4. 重新学习c++--理解引用、智能指针、虚函数、模板、容器

    最近几年用c和python比较多,上次用c++写程序已经是几年前的事情了.温故而知新,是时候重新学习下c++了. C++可以分成四大块去理解: C c++仍以C为基础,区块blocks.语句state ...

  5. c语言 ptr 用法,C++之智能指针std::shared_ptr简单使用和理解

    1  智能指针std::shared_ptr相关知识和如何使用 我们这里先说下智能指针std::shared_ptr,因为我看到我我们项目c++代码里面用得很多,我不是不会,所以记录学习下 先让ubu ...

  6. 【Android 10 源码】深入理解 software Codec2 服务启动

    MediaCodec 系列文章: [Android 10 源码]深入理解 MediaCodec 硬解码初始化 [Android 10 源码]深入理解 Omx 初始化 [Android 10 源码]深入 ...

  7. c++11 shared_ptr 与 make_shared源码剖析

    写在最前... 请支持原创~~ 0. 前言 所谓智能指针,可以从字面上理解为"智能"的指针.具体来讲,智能指针和普通指针的用法是相似的,不同之处在于,智能指针可以在适当时机自动释放 ...

  8. 【C++ 并发 线程池设计】深入理解C++线程池:设计、实现与应用

    目录标题 1. 引言 2. 线程池类设计 2.1 线程池类的主要成员变量 2.2 线程池类的构造函数和析构函数 3. 线程池任务的添加与执行 3.1 如何添加任务到线程池 3.2 如何在线程池中执行任 ...

  9. 指针、引用、const、类的浅显理解

    指针.引用.const.类的浅显理解 一.引用 1.1 理解与实验 和const 1.1.1 实验一 1.1.1 实验二 二.指针 三.指针和引用的区别 四.const(const和pointer) ...

最新文章

  1. [afterCode] docker 速成班 1: image
  2. linux c数字转字符串函数,Linux常用C函数—字符串转换篇
  3. 针对应用开发者的几点建议
  4. javaScript第二天(2)
  5. 1号店案例html源码_手把手教一起写jQuery版mini源码,分析jQuery的优势
  6. C语言学习笔记---结构体数组初始化
  7. 延时执行和取消延时执行
  8. angular环境配置
  9. 为计算机构建安全方案,计算机科学系安全管理标准化建设实施方案
  10. ES6、7学习笔记(尚硅谷)-2-let和const
  11. php 滑块验证,实现一个滑块验证功能
  12. 宋智孝那个机器人_陈柏霖机器人竟然冷落宋智孝
  13. 以HT82K629B为主控的程序员专用CV键盘(无需代码烧写)
  14. 人脸脸部识别技术_面部识别技术的危险后果
  15. Linux操作系统的性能将主要取决于,高校邦Linux操作系统安全与性能调优章节测试答案...
  16. 语音信号处理(一):对声母和韵母进行录音并时域分析
  17. 人脸属性分析--性别、年龄和表情识别(转)
  18. 发顶会论文,怎么就那么难?10个带你一起“收割”顶会论文的...
  19. Linux未来猜想:被遗忘还是终结Windows?
  20. Node.JS的魔力与神话

热门文章

  1. 2023上海国际烘焙展!
  2. Arch Linux 2208设置IP地址
  3. jQuery 删除元素
  4. STM32 你不知道的看门狗细节
  5. gitHub资源快速访问方法--jsDeliver
  6. matplotlib中的label标签
  7. Arduino ESP32 获取网络数据(HTTP POST方式)
  8. c语言机票座位预定系统_C语言实现飞机订票系统
  9. 前端常用Utils工具函数库合集
  10. tb文件 vivado_Vivado IDDR与ODDR原语的使用