• 如何用new来创建二维数组


    问题:如何用new来创建一个“R行C列的A类型的二维数组”呢?(注意,下文中的有些“数组”严格意义上不能叫数组……)

    方法1:指针的指针

    分别用new创建数组的每一“行”即可。

    int R = 2;
    int C = 3;
    auto ptr_2d = new A*[R]; //先new一个A*类型的“数组”
    for (int i = 0; i < R; i++) {
      ptr_2d[i] = new A[C]; //每个int*再指向一个A类型的“数组”
    }
    cout << "Type of ptr_2d: " << typeid(ptr_2d).name() << endl; //输出PP1A
    cout << "Type of ptr_2d[0]: " << typeid(ptr_2d[0]).name() << endl; //输出P1A
    

    这样的输出是(为了清晰,在A类型的构造函数和析构函数中都加上了输出语句):

    Constructing A...
    Constructing A...
    Constructing A...
    Constructing A...
    Constructing A...
    Constructing A...
    Type of ptr_2d: PP1A
    Type of ptr_2d[0]: P1A
    

    前六行说明我们确实成功创建了2*3=6个A类型对象。ptr_2d的类型是PP1A,即“A类型的指针的指针”,而ptr_2d[0]的类型是P1A,即“A类型的指针”。

    前文代码中可以发现,一个int *类型变量的typeid是Pi,而这里的ptr_2d[0]的typeid为何不是PA而是P1A呢?其实,这个1指的是是"A"这个类名的长度,如果把A改名叫Apple,那么这里输出的就应该是P5Apple了。

    这种方法是通用的,无论R和C是常量还是普通的变量都可以用。即使“二维数组”的每一“行”长度不一样,也可以用这种方法定义。

    这种方法定义的二维数组如何delete呢?记得new和delete要配对,既然我们写循环一行行new,自然也要写循环一行行delete。最后还要把一开始new的“int *”类型数组“ptr_2d”也delete掉。

    for (int i = 0; i < R; i++)
      delete[] ptr_2d[i];
    delete[] ptr_2d;
    

    输出:

    Deleting A...
    Deleting A...
    Deleting A...
    Deleting A...
    Deleting A...
    Deleting A...
    

    成功啦!

    但是要注意,这种方法定义的二维数组的每一“行”,在内存中不是连续的!实验:

    int R = 2;
    int C = 3;
    auto ptr_2d = new A*[R];
    for (int i = 0; i < R; i++) {
      ptr_2d[i] = new A[C];
    }
    auto last_ptr = &(ptr_2d[0][0]);
    for (int i = 0; i < 2; i++)
      for (int j = 0; j < 3; j++) {
        if ((i || j) && last_ptr + 1 != &(ptr_2d[i][j])) {
          cout << "Incontiguous memory between ptr_2d[" << i << "][" << j
            << "] (" << &(ptr_2d[i][j]) << ") and last_ptr ("
            << last_ptr << ")" << endl;
        }
        last_ptr = &(ptr_2d[i][j]);
      }
    

    这样会输出Incontiguous memory between ptr_2d[1][0] (0x7fdb36c05858) and last_ptr (0x7fdb36c05840),说明ptr_2d[1][0]ptr_2d[0][2]的地址之间的差别不是一个A类型对象的大小。

    方法2:数组的指针

    如果定义的二维数组只有第一位是普通变量、第二维是常量,则可以直接把每一行定义成定长的数组,写起来比较简单。如果要用这种方法定义更多维的数组,仍然只能有第一维可变,其余维度长度必须是常量。

    int R = 2;
    const int C = 3; //如果这里是int C = 3就不行了。
    auto ptr_2d = new A[R][C]; //当然,也可以是new A[R][3],3也是常量
    cout << "Type of ptr_2d: " << typeid(ptr_2d).name() << endl;
    cout << "Type of ptr_2d[0]: " << typeid(ptr_2d[0]).name() << endl;
    //do something...
    delete[] ptr_2d;
    

    输出:

    Constructing A...
    Constructing A...
    Constructing A...
    Constructing A...
    Constructing A...
    Constructing A...
    Type of ptr_2d: PA3_1A
    Type of ptr_2d[0]: A3_1A
    Deleting A...
    Deleting A...
    Deleting A...
    Deleting A...
    Deleting A...
    Deleting A...
    

    注意这次ptr_2d的类型变成了PA3_1A,表示它是{{长度为3的}{A类型的}数组}的指针}。(太过拗口,手动断句。)

    本文作者:胡小兔
    博客地址:http://rabbithu.cnblogs.com
  • 相关阅读:
    jquery的全选,全不选,反选
    jquery中的on方法绑定动态元素
    IIS服务器不能下载.apk文件的解决方略
    14:堆和堆排序
    虚拟内存
    leetcode28:实现strStr()
    leetcode387:字符串中的第一个唯一字符
    leetcode344:反转字符串
    leetcode198:打家劫舍
    leetcode64:最小路径和
  • 原文地址:https://www.cnblogs.com/RabbitHu/p/14616894.html
Copyright © 2020-2023  润新知