【问题标题】:How to reference objects in a 2 dimensional array?如何引用二维数组中的对象?
【发布时间】:2011-11-11 18:31:15
【问题描述】:

我读到你可以通过这一行声明一组对象

Enemy * d = new Enemy[2];

但是当我尝试创建一个二维数组时,出现了无法初始化的错误。我也试过这个

Enemy *enemies[6][2];

但我不确定如何引用该数组中的每个对象以及如何将该引用传递给函数。

【问题讨论】:

    标签: c++ oop multidimensional-array reference


    【解决方案1】:

    您需要使用指向指针的指针来创建锯齿状数组。

    Enemy** d = new Enemy*[6];
    for (size_t i = 0; i < 6; ++i)
        d[i] = new Enemy[2];
    

    如果您打算制作一个固定大小的数组,您可以像创建普通数组一样创建它。

    Enemy enemies[6][2];
    

    然后您只需使用两个索引来引用它们。

    enemies[2][1].roar();
    

    注意:您会发现多维数组往往会导致比其价值更令人头疼的问题。维护一个单维数组并简单地根据行数和列数对其进行索引会更简洁。

    Enemy* enemies = new Enemy[rows * cols];
    
    Enemy* getEnemy(size_t row, size_t col)
    {
        return enemies + (row * cols + col);
    }
    

    【讨论】:

    • 如果我在我的 main 中创建这些数组,我该如何将它传递给函数?
    • 你可以把它作为 foo(Enemy** array);如果你想要简单的方法。有一种更复杂的方法可以让您维护静态大小数组的类型信息,但我不会担心 - 指向像上面的 foo() 这样的指针就可以了。
    • 这取决于您如何制作数组以及如何处理它。如果您制作了一个锯齿状数组,则需要将其作为Enemy** 传递并同时传递两个维度。如果你做了一个固定大小的数组,你需要声明至少一个维度。 void kill(Enemy enemies[6][]);
    • 所有这些单独的分配都会损害缓存的局部性。此外,将它们明确化也意味着难以摆脱记忆。
    • 同意缓存位置。我在上面的答案中添加了注释。尽可能使用一维数组!
    【解决方案2】:

    如果你真的想在堆上分配一个二维数组,你可以这样做:

    Enemy (*enemies)[2] = new Enemy[6][2];
    

    但如果没有间接,它会简单得多:

    Enemy enemies[6][2];
    

    【讨论】:

      【解决方案3】:

      对于 C++,您应该使用 std::vectors 而不是 C 数组。

        std::vector<std::vector<Enemy> > d(6);
        for (size_t i = 0; i < 6; ++i)
             d[i].resize(2);
      
        //now d is ready to use
        d[1][2];
      

      【讨论】:

      • 但是使用该方法,您的元素在内存中不是连续的(因为内部向量都使用单独的分配),并且每次访问都包含一个额外的重定向。由于缓存局部性(或者更确切地说,缺乏缓存),两者都可能会损害您的性能。相反,使用具有 2*6 元素的单个向量,并使用索引算法访问它(最好封装在一个不错的类中)。
      • 是的,我其实不支持这个答案。您应该只在需要自动内存增长的非常特殊的情况下使用向量。否则,您最好不要使用 STL 的所有多余内容,只分配一个数组 ONCE。
      【解决方案4】:

      你会的

      Enemy (*enemies)[2] = new Enemy[6][2];
      

      也就是说,一个指向 2 个敌人的数组的指针。 请注意,只有第一个数组级别可以作为指针,因此在运行时确定。

      另请注意,您的第二个定义创建了一个指向敌人的 6*2 指针数组。假设您已将它们全部初始化,您将使用*enemies[j][k] 访问它们,或者如果每个指针本身都指向一个数组,则使用enemies[j][k][l]

      注意,如果你想在运行时确定两个索引,你应该分配一个大数组并使用索引算法:

      敌人*敌人 = 新敌人[6*2]; // 访问元素 (j,k) 敌人[6*j+k].fight();

      当然,通常最好使用vector&lt;Enemy&gt;,除非您的类Enemy 不适合向量,例如因为它不能被复制(分别在 C++11 中,移动)。此外,当以这种方式处理多维数组时,理想情况下,您应该将数组和索引逻辑封装在一个类中。

      【讨论】:

        猜你喜欢
        • 2017-11-09
        • 2011-04-25
        • 2021-06-14
        • 2021-11-23
        • 2015-08-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多