12.2 动态数组

  C++语言和标准库提供了两种一次分配一个对象数组的方法。C++语言定义了另一种new表达语法,可以分配并初始化一个对象数组。

new和数组

  为了让new分配一个对象数组,我们要在类型名之后跟一对方括号,在其中要指明分配的对象的数目。

//调用get_size确定分配多少个int
int *pia=new int[get_size()];   //pia指向第一个int

  方括号中的大小必须是整型,但不必是常量。
  也可以用一个表示数组类型的类型别名来分配一个数组:

typedef int arrT[42];  //arrT表示42个int的数组类型
int *p=new arrT;  //分配一个42个int的数组;p指向第一个int

  分配一个数组会得到一个元素类型的指针
  当用new分配一个数组时,我们并未得到一个数组类型的对象,而是得到一个数组元素类型的指针。因此不能对动态数组调用begin或end,也不能使用范围for语句来处理动态数组中的元素。

  初始化动态分配对象的数组
  默认情况下, new分配的对象都是默认初始化的,可以对数组中的元素进行值初始化:

int *pia=new int[10];  //10个未初始化的int
int *pia2=new int[10();  //10个值初始化为0的int
string *psa=new string[10];  //10个空string
string *psa2=new string[10]();  //10个空string
//10个int分别用列表中对应的初始化器初始化
int *pia3=new int[10] {0,1,2,3,4,5,6,7,8,9};
//10个string,前4个用给定的初始化器初始化,剩余的进行值初始化
string *psa3=new string[10] {"a","an","the",string(3,'x')};

  动态分配一个空数组是合法的
  当我们用new分配一个大小为0的数组时,new返回一个合法的非空指针。此指针保证与new返回的其他任何指针都不相同。对于零长度的数组来说,此指针就像尾后指针一样,我们可以像使用尾后迭代器一样使用这个指针。

  释放动态数组
  为了释放动态数组,我们使用一种特殊形式的delete——在指针前面加上一个空方括号对:

delete p;  //p必须指向一个动态分配的对象或为空
delete[] pa;  //pa必须指向一个动态分配的数组或为空

  智能指针与动态数组
  标准库提供了一个可以管理new分配的数组的unique_ptr版本。为了用一个unique_ptr管理动态数组,我们必须在对象类型后面跟一对空方括号:

//up指向一个包含10个未初始化int的数组
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;  //为每个元素赋予一个新值

  与unique_ptr不同,shared_ptr不直接支持管理动态数组。如果希望使用shared_ptr管理一个动态数组,必须提供自己定义的删除器。shared_ptr未定义下标运算符,而且智能指针类型不支持指针算术运算。因此,为了访问数组中的元素,必须使用get获取一个内置指针,然后用它来访问数组元素:

for(size_t i=0; i!=10;++i)
      *(sp.get()+i)=i;  //使用get获取一个内置指针

allocator类

  标准库allocator类定义在头文件memory中,它帮助我们将内存分配和对象构造分离开来,它提供一种类型感知的内存分配方法,它分配的内存是原始的、未构造的。
  类似vector,allocator是一个模板。为了定义一个allocator对象,我们必须指明这个allocator可以分配的对象类型:

allocator<string> alloc;
auto const p=alloc.allocate(n);  //分配n个未初始化的string

  这个allocate调用为n个string分配内存

  allocator分配未构造的内存
  allocator分配的内存是未构造的。我们按需要在此内存中构造对象,construct成员函数接受一个指针和零个或多个额外参数,在给定位置构造一个元素。额外参数用来初始化构造的对象。

auto q=p;  //q指向最后构造的元素之后的位置
alloc.construct(q++);  //*q为空字符串
alloc.construct(q++,10,'c');   //*q为cccccccccc
alloc.construct(q++,"hi");  //*q为hi!

  当我们用完对象后,必须对每个构造的元素调用destroy来销毁它们。函数destroy接受一个指针,对指向的对象执行析构函数:

while(q!=p)
      alloc.destroy(--q);   //释放我们真正构造的string

  一旦元素被销毁后,就可以重新使用这部分内存来保存其他string,也可以将其归还系统,释放内存通过调用deallocate来完成:

alloc.deallocate(p,n);

  我们传递给deallocate的指针不能为空,它必须指向由allocate分配的内存。而且,传递给deallocate的大小参数必须与调用allocated分配的内存时提供的大小参数具有一样的值。

  拷贝与填充未初始化内存的算法
  标准库还为allocator类定义了两个伴随算法,可以在未初始化内存中创建对象:uninitialized_copy,unitialized_fill。

//分配比vi周年元素所占空间大一倍的动态内存
auto p=alloc.allocate(vi.size()*2);
//通过拷贝vi中的元素来构造从p开始的元素
auto q=unitialized_copy(vi.begin(),vi.end(),p);
//将剩余元素初始化为2
unitialized_fill_n(q,vi.szie(),42);
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,651评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,468评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,931评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,218评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,234评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,198评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,084评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,926评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,341评论 1 311
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,563评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,731评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,430评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,036评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,676评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,829评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,743评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,629评论 2 354

推荐阅读更多精彩内容

  • 动态数组 new和delete运算符一次分配/释放一个对象,但某些应用需要一次为很多对象分配内存,如vector和...
    Kreat阅读 1,607评论 0 0
  • new和delete只能一次分配释放一个对象,一些场合,我们需要一次为很多对象分配内存,为了支持这种需求,C++标...
    saviochen阅读 489评论 0 4
  • #1.动态内存与智能指针1.1 shared_ptr类1.2 直接管理内存1.3 shared_ptr和new结合...
    MrDecoder阅读 508评论 0 4
  • 静态内存、栈内存和堆 我们前面只提到了静态内存或栈内存: 静态内存:用来保存局部static、类static数据成...
    TOMOCAT阅读 281评论 0 1
  • 12.1 智能指针 智能指针行为类似普通指针,但它负责自动释放所知的对象。 #include <memory> s...
    龙遁流阅读 362评论 0 1