动态数组的分配和释放

  • new和数组
C++语言和标准库提供了一次分配一个对象数组的方法,定义了另一种new表达式语法。我们需要在类型名后跟一对方括号,在其中指明要分配的对象的数目。
int* arr = new int[20]; // arr 指向第一个int

方括号中的大小必须是整数,但不必是常量。

可以使用typedef来表示数组类型的别名:
typedef int arrT[42];
int* p = new arrT; // 分配一个42个int的数组,p指向第一个int

虽然我们通常称 new T[ ] 分配的内存为 “动态数组”, 这种叫法在某种程度上来说有些误导。使用new分配一个数组时,我们只是获得了一个数组元素类型的指针,并未获得一个数组类型的对象。因此,动态数组并不是数组类型。因此,不能对动态数组使用begin()和end(),这些函数使用数组的维度,也不能处理数组中的元素,比如for语句。

  • 初始化动态分配对象的数组
可以对new分配的动态数组进行值初始化,方法时在大小后面跟一对空括号:
int* pia = new int[10]; // 10个未初始化的int
int* pia1 = new int[10](); // 10个值初始化的int
string* psa = new string[10]; // 10个空string
string* psa = new string[10](); // 10个空string

新标准中,我们可以提供一个元素初始化器的花括号列表:

int* pia2 = new int[10]{0, 1, 2, 3, 4, 5, 6};

如果花括号中的元素个数少于分配对象个数,剩余的元素进行值初始化,如果元素个数多余对象个数,则new表达式失败,不会分配内存。new会抛出一个bad_array_new_length的异常,类似bad_alloc,该异常类型定义在头文件 <new>中。

new一个非数组对象时,我们可以在初始化括号中给出一个初始化器,依靠这个初始化器,我们可以使用auto来分配数组,但是对于数组,这种做法是不允许的。
  • 动态分配一个空数组是合法的
我们在使用new分配一个动态数组时,可以指定分配数组的大小为0,这样做是合法的:
char* pc = new char(0);

此时new返回一个与其他new表达式返回类型都不同的指针类型,该指针不能解引用,就像一个数组的尾后迭代器一样。

  • 释放动态数组
释放动态数组,我们需要在delete和数组名之间加一个空的方括号[ ] , 表示我们释放的是一个动态数组。
数组中的元素逆序销毁,即,最后一个元素首先被销毁,然后是倒数第二个,依次类推。
当我们释放一个动态数组时,空方括号是必须的,它指示编译器此指针指向一个对象数组的第一个元素。 delete一个动态数组时未添加空方括号或delete一个普通指针时添加了空方括号,其行为都是未定义的。
前面我们讲到,可以使用typedef来给动态数组起一个别名,这样在new一个动态数组时就不必添加方括号[],即使这样,我们在释放一个动态数组时,仍然需要添加方括号[],因为它本质上还是一个动态数组。

智能指针和动态数组

unique_ptr智能指针有个可以管理new分配的动态数组的版本,为了使用一个unique_ptr来管理动态数组,需要在对象类型后加一个空方括号[]:
unique_ptr<int[]> up(new int[10]());
up.release(); // 自动调用delete []销毁其指针

当一个unique_ptr指向一个数组时,我们不能使用点和箭头成员运算符,毕竟,unique_ptr指向的是一个数组而不是单个对象。不过,我们可以使用下表运算符来访问数组中的元素:

for (size_t i = 0; i < 10; ++i)
up[i] = i;

shared_ptr不支持动态数组,如果希望使用shared_ptr管理一个动态数组,我们需要提供自己的删除器:

shared_ptr<int> sp(new int[10], [](int* p){ delete [] p; });
sp.reset();

我们在这个例子中使用lambda做为shared_ptr的删除器,如果我们不提供删除器,这样的行为是未定义的,因为默认情况下shared_ptr使用delete来释放内存,使用delete来释放一个动态数组的定位是未定义的。

shared_ptr不支持动态数组这一特性会影响我们访问数组中的元素:
for (size_t i = 0; i != 10; ++i)
*(sp.get() + i) = i;

shared_ptr没有定义下标运算符,而且智能指针不支持指针算术运算。因此,为了访问数组中的元素,我们必须用get成员函数获取一个内置指针,然后使用该内置指针来访问数租元素。

C++ Primer : 第十二章 : 动态内存之动态数组的更多相关文章

  1. C++ Primer : 第十二章 : 动态内存之shared_ptr与new的结合使用、智能指针异常

    shared_ptr和new结合使用 一个shared_ptr默认初始化为一个空指针.我们也可以使用new返回的指针来初始化一个shared_ptr: shared_ptr<double> ...

  2. C++ Primer : 第十二章 : 动态内存之动态内存管理(new和delete)

    C++语言定义了两个运算符来分配和释放动态内存:运算符new分配内存,运算符delete释放new分配的内存. 运算符new和delete 使用new动态分配和初始化对象 在自由空间分配的内存是无名的 ...

  3. C++ Primer : 第十二章 : 动态内存之shared_ptr类实例:StrBlob类

    StrBlob是一个管理string的类,借助标准库容器vector,以及动态内存管理类shared_ptr,我们将vector保存在动态内存里,这样就能在多个对象之间共享内存. 定义StrBlob类 ...

  4. C++ Primer : 第十二章 : 动态内存之shared_ptr类

    在C++中,动态内存是的管理是通过一对运算符来完成的:new  ,在动态内存中为对象分配空间并返回一个指向该对象的指针,delete接受一个动态对象的指针,销毁该对象,并释放该对象关联的内存. 动态内 ...

  5. Linux内核设计与实现 总结笔记(第十二章)内存管理

    内核里的内存分配不像其他地方分配内存那么容易,内核的内存分配不能简单便捷的使用,分配机制也不能太复杂. 一.页 内核把页作为内存管理的基本单位,尽管处理器最小寻址坑是是字或者字节.但是内存管理单元MM ...

  6. C++Primer 第十二章

    //1.标准库提供了两种智能指针类型来管理动态对象,均定义在头文件memory中,声明在std命名空间. // shared_ptr:允许多个指针指向同一个对象. // unique_ptr:独占所指 ...

  7. C++ Primer : 第十二章 : 动态内存之allocator类

    标准库allocator类定义在头文件 <memory>中.它帮助我们将内存分配和构造分离开来,它分配的内存是原始的.未构造的. 类似vector,allocator也是一个模板类,我们在 ...

  8. C++ Primer : 第十二章 : 动态内存之unique_ptr和weak_ptr

    unique_ptr 一个unique_ptr拥有它所管理的对象,与shared_ptr不同,unique_ptr指向的对象只能有一个用户.当unique_ptr被销毁后,它所指向的对象也被销毁. 定 ...

  9. C++ Primer : 第十二章 : 文本查询程序

    C++ Primer书上这个例子讲的很不错,写写帮助自己理解标准库和智能指针. .h 文件内容 #include <fstream> #include <iostream> # ...

随机推荐

  1. Linux配置防火墙 开启80端口

    vi /etc/sysconfig/iptables -A INPUT -m state –state NEW -m tcp -p tcp –dport 80 -j ACCEPT(允许80端口通过防火 ...

  2. wp8.1 Study1: 页面导航&页面间值传递

    摘要:wp8.1与wp8中很多API是不一样了,wp8.1把以前wp7.x时的api去掉了,更多与win8.1的API相似.比如以下的页面导航和页面之间的值传递 1.页面导航 利用Frame.Navi ...

  3. IOS弹出视图 LewPopupViewController

    LewPopupViewController是一款IOS弹出视图软件.iOS 下的弹出视图.支持iPhone/iPad. 软件截图 使用方法 弹出视图 1 2 3 4 5 PopupView *vie ...

  4. JVM-class文件完全解析-访问标志

    访问标志 在前面分析了 class文件的魔数,次版本号,主版本号,常量池入口,常量池,那么在常量池结束后,紧接着的两个字节代表访问标志(access_flages).这个标志用于识别一些类或者接口层次 ...

  5. php的数组与数据结构

    一.数组的分类与定义 分类: 1.索引数组  $array = array(1,2,3,4,5); 2.关联数组  $array=array(1=>"aa","bb ...

  6. 一篇介绍jquery中的ajax的结合

    <script type="text/javascript">        function Text_ajax()        {           $.aja ...

  7. 配置navigation bar外观

    /* 配置navigation bar外观开始 */ self.navigationBar.translucent = YES; self.navigationBar.titleTextAttribu ...

  8. 扩展jQuery easyui datagrid增加动态改变列编辑的类型

    $.extend($.fn.datagrid.methods, { addEditor : function(jq, param) { if (param instanceof Array) { $. ...

  9. libbspatch.so

    http://www.zhihu.com/question/21154099 http://blog.csdn.net/hmg25/article/details/8100896 91助手和Googl ...

  10. js控制打印 转的

    很多时候,我们在做系统的时候要做打印功能,打印在js中其实很简单,不过这个很简单的代码并不能满足我们的特定需求,比如我们需要打印的表单在很多文字的中间,或者文字中包含一些广告或者图片什么的,这就很难用 ...