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操作,可以放心地使用了。

不过这么做的缺点也是很明显的:

  1. 我们想管理的值是int[]类型的,然而事实上传给模板参数的是int
  2. 需要显示提供delete functor
  3. 不能使用std::make_shared,无法保证异常安全
  4. 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和动态数组的更多相关文章

  1. C++ Primer 笔记——动态数组

    1.动态数组定义时也需要指明数组的大小,但是可以不是常量. int i; int arr[i]; // 错误,数组的大小必须为常量 int *p = new int[i]; // 正确,大小不必是常量 ...

  2. C++ Primer : 第十二章 : 动态内存之动态数组

    动态数组的分配和释放 new和数组 C++语言和标准库提供了一次分配一个对象数组的方法,定义了另一种new表达式语法.我们需要在类型名后跟一对方括号,在其中指明要分配的对象的数目. int* arr ...

  3. 【足迹C++primer】40、动态数组

    动态数组 C++语言定义了第二种new表达式语法.能够分配并初始化一个对象数组.标准库中包括 一个名为allocator的类.同意我们将分配和初始化分离. 12.2.1 new和数组 void fun ...

  4. 动态数组、allocator 类

    12.2 动态数组 12.2.1 new 和数组 1.分配一个动态数组即是在分配一个new对象时在类型名之后加一对方括号,用来存放数组大小,该数可以是任意表达式.也可以是0,只需是整形.无需是常量.数 ...

  5. 常用数据结构-线性表及Java 动态数组 深究

    [Java心得总结六]Java容器中——Collection在前面自己总结的一篇博文中对Collection的框架结构做了整理,这里深究一下Java中list的实现方式 1.动态数组 In compu ...

  6. C语言 · 动态数组的使用

    从键盘读入n个整数,使用动态数组存储所读入的整数,并计算它们的和与平均值分别输出.要求尽可能使用函数实现程序代码.平均值为小数的只保留其整数部分. 样例输入: 5 3 4 0 0 2样例输出:9 1样 ...

  7. C++中关于[]静态数组和new分配的动态数组的区别分析

    这篇文章主要介绍了C++中关于[]静态数组和new分配的动态数组的区别分析,很重要的概念,需要的朋友可以参考下 本文以实例分析了C++语言中关于[]静态数组和new分配的动态数组的区别,可以帮助大家加 ...

  8. C++之动态数组

    C99支持一种名为变长数组的结构来方便程序员.C++也提供了一种长度可在程序运行时确定的数组类型:动态数组.声明格式为:(声明 int 类型的数组) ; //此处可修改 ArraySize 的值 in ...

  9. VB默认属性、动态数组、Range对象的默认属性的一点不成熟的想法

    1.默认属性 VB6.0有默认属性的特性.当没有给对象指定具体的属性时,"默认属性"是VB6.0将使用的属性.在某些情形下,省略常用属性名,使代码更为精简. 因为CommandBu ...

随机推荐

  1. Appium 【已解决】提示报错:Attempt to re-install io.appium.android.ime without first uninstalling.

    详细报错:Failed to install D:\AutoTest\appium\Appium\node_modules\appium\build\unicode_ime_apk\UnicodeIM ...

  2. RVM 安装 Ruby

    RVM 是一个命令行工具,可以提供一个便捷的多版本 Ruby 环境的管理和切换. https://rvm.io/ 如果你打算学习 Ruby / Rails, RVM 是必不可少的工具之一. 这里所有的 ...

  3. 十分钟学会Java8的lambda表达式和Stream API

    01:前言一直在用JDK8 ,却从未用过Stream,为了对数组或集合进行一些排序.过滤或数据处理,只会写for循环或者foreach,这就是我曾经的一个写照. 刚开始写写是打基础,但写的多了,各种乏 ...

  4. MySQL 中基于 XA 实现的分布式事务

    1 XA协议 首先我们来简要看下分布式事务处理的XA规范可知XA规范中分布式事务有AP,RM,TM组成: 其中应用程序(Application Program ,简称AP):AP定义事务边界(定义事务 ...

  5. Vue.js 牛刀小试(持续更新~~~)

    一.前言 这个系列的文章开始于今年9月从上一家公司辞职后,在找工作的过程中,觉得自己应该学习一些新的东西,从前几章的更新日期也可以看出,中间隔了很长的时间,自己也经历了一些事情,既然现在已经稳定了,就 ...

  6. Firemonkey 原生二维码扫描优化

    之前用了ZXing的Delphi版本,运行自带的例子,速度非常慢,与安卓版本的相比查了很多,因此打算使用集成jar的方法,但是总觉得美中不足. 经过一番研究,基本上解决了问题. 主要有两方面的优化: ...

  7. Android:JNI与NDK(一)

    友情提示:欢迎关注本人公众号,那里有更好的阅读体验以及第一时间获取最新文章 本篇目录 以下举例代码均来自:NDK示例代码 一.前言 安卓开发中很多场景需要用到NDK来开发,比如,音视频的渲染,图像的底 ...

  8. VS2017、VS2019没有Setup安装项目(Visual Studio Installer)_解决方案

    前言: VS2010中有一个自带的安装部署项目,叫:Visual Studio Installer ,我们通常称为:setup项目,是一个用于自定义安装部署的项目方案.但是在VS2017,VS2019 ...

  9. maven下载及安装最详解

    maven的下载及安装 1.maven下载地址:https://maven.apache.org/download.cgi 2.将下载的安装包解压到自定义目录 3.配置环境变量 此电脑->右键属 ...

  10. 什么是CSS

    CSS是Cascading Style Sheet的缩写.译作”层叠样式表单“.是用于(增强)控制网页样式并允许将样式信息与网页内容分离的一种标记性语言.使用CSS样式可以控制许多仅使用HTML无法控 ...