make_shared理解
本章所有内容均从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理解相关推荐
- C++ 智能指针std::shared_ptr简单使用和理解
参考:https://blog.csdn.net/u011068702/article/details/83692838 1 智能指针std::shared_ptr相关知识和如何使用 我们这里先说下 ...
- 深入理解C++内存管理
深入理解C++内存管理 一文了解所有C++内存的问题 AlexCool 目录 一 C++内存模型 二 C++对象内存模型 三 C++程序运行内存空间模型 四 C++栈内存空间模型 五 C++堆内 ...
- 看完这个你还不理解右值引用和移动构造 你就可以来咬我(下)
共分三篇,这是第3篇.另外两篇,看完这个你还不理解右值引用和移动构造 你就可以来咬我(上),看完这个你还不理解右值引用和移动构造 你就可以来咬我(中). 下面是新标准下的其他特性(共十点),了解一下, ...
- 重新学习c++--理解引用、智能指针、虚函数、模板、容器
最近几年用c和python比较多,上次用c++写程序已经是几年前的事情了.温故而知新,是时候重新学习下c++了. C++可以分成四大块去理解: C c++仍以C为基础,区块blocks.语句state ...
- c语言 ptr 用法,C++之智能指针std::shared_ptr简单使用和理解
1 智能指针std::shared_ptr相关知识和如何使用 我们这里先说下智能指针std::shared_ptr,因为我看到我我们项目c++代码里面用得很多,我不是不会,所以记录学习下 先让ubu ...
- 【Android 10 源码】深入理解 software Codec2 服务启动
MediaCodec 系列文章: [Android 10 源码]深入理解 MediaCodec 硬解码初始化 [Android 10 源码]深入理解 Omx 初始化 [Android 10 源码]深入 ...
- c++11 shared_ptr 与 make_shared源码剖析
写在最前... 请支持原创~~ 0. 前言 所谓智能指针,可以从字面上理解为"智能"的指针.具体来讲,智能指针和普通指针的用法是相似的,不同之处在于,智能指针可以在适当时机自动释放 ...
- 【C++ 并发 线程池设计】深入理解C++线程池:设计、实现与应用
目录标题 1. 引言 2. 线程池类设计 2.1 线程池类的主要成员变量 2.2 线程池类的构造函数和析构函数 3. 线程池任务的添加与执行 3.1 如何添加任务到线程池 3.2 如何在线程池中执行任 ...
- 指针、引用、const、类的浅显理解
指针.引用.const.类的浅显理解 一.引用 1.1 理解与实验 和const 1.1.1 实验一 1.1.1 实验二 二.指针 三.指针和引用的区别 四.const(const和pointer) ...
最新文章
- [afterCode] docker 速成班 1: image
- linux c数字转字符串函数,Linux常用C函数—字符串转换篇
- 针对应用开发者的几点建议
- javaScript第二天(2)
- 1号店案例html源码_手把手教一起写jQuery版mini源码,分析jQuery的优势
- C语言学习笔记---结构体数组初始化
- 延时执行和取消延时执行
- angular环境配置
- 为计算机构建安全方案,计算机科学系安全管理标准化建设实施方案
- ES6、7学习笔记(尚硅谷)-2-let和const
- php 滑块验证,实现一个滑块验证功能
- 宋智孝那个机器人_陈柏霖机器人竟然冷落宋智孝
- 以HT82K629B为主控的程序员专用CV键盘(无需代码烧写)
- 人脸脸部识别技术_面部识别技术的危险后果
- Linux操作系统的性能将主要取决于,高校邦Linux操作系统安全与性能调优章节测试答案...
- 语音信号处理(一):对声母和韵母进行录音并时域分析
- 人脸属性分析--性别、年龄和表情识别(转)
- 发顶会论文,怎么就那么难?10个带你一起“收割”顶会论文的...
- Linux未来猜想:被遗忘还是终结Windows?
- Node.JS的魔力与神话