shared_ptr和动态数组
std::shared_ptr
智能指针是c++11一个相当重要的特性,可以极大地将开发者从资源申请/释放的繁重劳动中解放出来。
然而直到c++17前std::shared_ptr
都有一个严重的限制,那就是它并不支持动态数组:
#include <memory>
std::shared_ptr<int[]> sp1(new int[10]()); // 错误,c++17前不能传递数组类型作为shared_ptr的模板参数
std::unique_ptr<int[]> up1(new int[10]()); // ok, unique_ptr对此做了特化
std::shared_ptr<int> sp2(new int[10]()); // 错误,可以编译,但会产生未定义行为,请不要这么做
sp1
错误的原因很明显,然而sp2
的就没有那么好找了,究其原因,是因为std::shared_ptr
对非数组类型都使用delete p
释放资源,显然这对于new int[10]
来说是不对的,对它应该使用delete [] p
。
其实c++17前的解决方案并不复杂,我们可以借助std::default_delete
,它用于提供对应类型的正确的delete操作:
std::shared_ptr<int> sp3(new int[10](), std::default_delete<int[]>());
现在我们提供了正确的delete操作,可以放心地使用了。
不过这么做的缺点也是很明显的:
- 我们想管理的值是int[]类型的,然而事实上传给模板参数的是int
- 需要显示提供delete functor
- 不能使用
std::make_shared
,无法保证异常安全 - c++17前shared_ptr未提供
opreator[]
,所以当需要类似操作时不得不使用sp3.get()[index]
的形式
事实上共享一片连续分配内存的需求是极为常见的,所以为了修正上述缺陷,c++17以及即将推出的c++2a对std::shared_ptr
做了完善。
先说c++17的改进,shared_ptr增加了opreator[]
,并可以使用int[]
类的数组类型做模板参数,所以sp3
的定义可以简化了:
std::shared_ptr<int[]> sp3(new int[10]());
对于访问分配的空间,可以将sp3.get()[index]
替换为sp3[index]
。看个具体的例子:
#include <iostream>
#include <memory>
int main()
{
std::shared_ptr<int[]> sp(new int[5]());
for (int i = 0; i < 5; ++i) {
sp[i] = (i+1) * (i+1);
}
for (int i = 0; i < 5; ++i) {
std::cout << sp[i] << std::endl;
}
}
我们分配一个有5个int元素的动态数组,然后分别赋值1-5的平方,然后输出:
g++ -Wall -std=c++17 test.cpp
./a.out
1
4
9
16
25
使用被极大得简化了,然而还是有点问题,那就是无法使用std::make_shared
,而我们除非指定自己的delete functor,否则我们应该尽量使用std::make_shared
。
所以c++20对此做了改进:
auto up2 = std::make_unique<int[]>(10); // 从c++14开始,分配一个管理有10个int元素的动态数组的unique_ptr
// c++2a中你可以这样写,与上一句相似,只不过返回的是shared_ptr
auto sp3 = std::make_shared<int[]>(10);
在我的编译器上(GCC 8.2.1)还不能支持这一特性,所以很遗憾得不能提供演示了。
不过等c++2a(很可能就叫c++20)发布后std::shared_ptr
就能安全而便捷地管理动态数组了。
shared_ptr和动态数组的更多相关文章
- C++ Primer 笔记——动态数组
1.动态数组定义时也需要指明数组的大小,但是可以不是常量. int i; int arr[i]; // 错误,数组的大小必须为常量 int *p = new int[i]; // 正确,大小不必是常量 ...
- C++ Primer : 第十二章 : 动态内存之动态数组
动态数组的分配和释放 new和数组 C++语言和标准库提供了一次分配一个对象数组的方法,定义了另一种new表达式语法.我们需要在类型名后跟一对方括号,在其中指明要分配的对象的数目. int* arr ...
- 【足迹C++primer】40、动态数组
动态数组 C++语言定义了第二种new表达式语法.能够分配并初始化一个对象数组.标准库中包括 一个名为allocator的类.同意我们将分配和初始化分离. 12.2.1 new和数组 void fun ...
- 动态数组、allocator 类
12.2 动态数组 12.2.1 new 和数组 1.分配一个动态数组即是在分配一个new对象时在类型名之后加一对方括号,用来存放数组大小,该数可以是任意表达式.也可以是0,只需是整形.无需是常量.数 ...
- 常用数据结构-线性表及Java 动态数组 深究
[Java心得总结六]Java容器中——Collection在前面自己总结的一篇博文中对Collection的框架结构做了整理,这里深究一下Java中list的实现方式 1.动态数组 In compu ...
- C语言 · 动态数组的使用
从键盘读入n个整数,使用动态数组存储所读入的整数,并计算它们的和与平均值分别输出.要求尽可能使用函数实现程序代码.平均值为小数的只保留其整数部分. 样例输入: 5 3 4 0 0 2样例输出:9 1样 ...
- C++中关于[]静态数组和new分配的动态数组的区别分析
这篇文章主要介绍了C++中关于[]静态数组和new分配的动态数组的区别分析,很重要的概念,需要的朋友可以参考下 本文以实例分析了C++语言中关于[]静态数组和new分配的动态数组的区别,可以帮助大家加 ...
- C++之动态数组
C99支持一种名为变长数组的结构来方便程序员.C++也提供了一种长度可在程序运行时确定的数组类型:动态数组.声明格式为:(声明 int 类型的数组) ; //此处可修改 ArraySize 的值 in ...
- VB默认属性、动态数组、Range对象的默认属性的一点不成熟的想法
1.默认属性 VB6.0有默认属性的特性.当没有给对象指定具体的属性时,"默认属性"是VB6.0将使用的属性.在某些情形下,省略常用属性名,使代码更为精简. 因为CommandBu ...
随机推荐
- github上传文件的几句命令行
1.首先进入要上传的本地目录,右键打开git命令行. 2.执行指令:git init 初始化本地仓库,这是会看到多了一个.git文件夹(如果没看到那就是电脑隐藏了). 3.执行命令:git ad ...
- Https协议与HttpClient的实现
一.背景 HTTP是一个传输内容有可读性的公开协议,客户端与服务器端的数据完全通过明文传输.在这个背景之下,整个依赖于Http协议的互联网数据都是透明的,这带来了很大的数据安全隐患.想要解决这个问题有 ...
- Java基础系列之你真的懂==与equals的区别吗?
对于Java初学者而言,可能会对这两个比较方法比较模糊,有的人可能会觉得两个的方法使用起来结果是一样的等.如果你有这样的想法,我建议你来看看这边博客,让你充分了解这两个比较的异同,以及他们底层是如何比 ...
- 七牛云免费对象存储,并绑定到cloudreve中
之前开通了腾讯云的对象存储COS并使用中,不过之前主要将它当作云盘使用,这两天再做博客系统时发现也可以将它作为网站的图库,这样对网站的访问效率也会提高. 今天了解到七牛云有免费的对象存储可以使用,于是 ...
- ssm上传图片
ssm上传图片 1 需求 添加客户时上传图片和客户修改信息是上传图片. 2 思路 首先,数据库创建pic字段,类型为varchar,通过逆向工程重新生成mapper接口和xml文件 ...
- EFCore动态切换Schema
最近做个分库分表项目,用到schema的切换感觉还是有些坑的,在此分享下. 先简要说下我们的分库分表 分库分表规则 我定的规则是,订单号(数字)除以16,得出的结果为这个订单所在的数据库,然后他的余数 ...
- 程序员如何让自己 Be Cloud Native - 配置篇
前言 这是<程序员如何让自己 Be Cloud Native>系列文章的第二篇,从第一篇的反馈来看,有些同学反馈十二要素太形式主义,不建议盲目跟从.作者认为任何理论和技术都需要有自己的观点 ...
- 在个人博客中优雅的使用Gitalk评论插件
在上一篇博客<程序员如何从0到1搭建自己的技术博客>中,我们了解了如何快速的从0到1搭建一个个人博客. 其实细心的你会发现,该博客用到了一个评论插件,这个插件就是Gitalk. 如果想要在 ...
- 还在用AIDL吗?试试EasyMessenger吧
EasyMessenger 直达Github项目地址 一款用于Android平台的基于Binder的进程间通信库,采用annotationProcessor生成IPC通信需要的代码.EasyMesse ...
- windows powershell基础
windows powershell基础 目录: 1.管道和重定向 2.命令执行 3.变量 4.数组和哈希表 #@()创建数组,使用","把每个值分隔开,@{}创建哈希表,用&qu ...