zoukankan      html  css  js  c++  java
  • C++ Primer : 第十二章 : 动态内存之动态数组

    动态数组的分配和释放

    • 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成员函数获取一个内置指针,然后使用该内置指针来访问数租元素。



  • 相关阅读:
    Bounded Context
    Unity3D研究院之IOS本地消息通知LocalNotification的使用(六十七)
    SVN服务器搭建和使用
    进度条
    XQuery获取节点的属性名与值
    AnimatorStateInfo
    Unity3D 中脚本执行的先后顺序
    Unity里面的自动寻路(二)
    Unity里面的自动寻路(一)
    java遍历文件夹两种方式
  • 原文地址:https://www.cnblogs.com/averson/p/5096059.html
Copyright © 2011-2022 走看看