【问题标题】:C++ Returning and Inserting a 2D array objectC++ 返回和插入二维数组对象
【发布时间】:2010-09-28 23:33:31
【问题描述】:

我正在尝试从一个较小的二维数组对象返回一个数组数据成员,并尝试将该数组插入到一个较大的二维数组对象中。但是在尝试这个时,我遇到了两个问题。

第一个问题是我想返回二维数组的名称,但我不知道如何正确地返回二维数组名称。

这就是我的二维数组数据成员的样子

私人的: intpieceArray[4][4]; // 2D 较小的数组

我想将此数组返回到一个函数中,但这会导致编译器错误:

int Piece::returnPiece() { 返回片数组; //无效 // 返回二维数组名 }

我厌倦了使用这种返回类型并且它起作用了:

int Piece::returnPiece() { 返回片数组[4][4]; }

但我不确定这是否是我想要的,因为我想返回数组及其所有内容。

另一个问题是 InsertArray() 函数,我会将 returnPiece() 函数放在 InsertArray() 的参数中。

InsertArray() 的问题在于参数,这里是它的代码:

void Grid::InsertArray( int arr[4][4] ) //编译器接受,但不起作用 { for(int i = 0; i &lt x_ROWS ; ++i) { for (int j = 0; j &lt y_COLUMNS ; ++j) { 平方[i][j] = arr[i][j]; } } }

这样做的问题是它不接受我的 returnPiece(),如果我删除“[4][4]”,我的编译器不接受。

这些大多都是语法错误,但是我该如何解决这些问题呢?

  1. 在 returnPiece() 中返回整个pieceArray
  2. InsertArray() 中参数的正确语法
  3. InsertArray() 的参数接受 returnPiece()

这三个是我需要帮助的主要问题,当我尝试使用指针指针方法时也遇到了同样的问题。有谁知道如何解决这三个问题?

【问题讨论】:

    标签: c++ arrays syntax 2d


    【解决方案1】:

    您似乎需要详细了解 C++ 中的指针以及按引用传递与按值传递。

    您的 returnPiece 方法被定义为返回单个单元格的值。给定索引(例如 [4][4]),您将返回该单元格内容的副本,因此您将无法更改它,或者更准确地说,更改它会更改副本。

    我相信有人会给你正确的语法,但我真的建议你学习这些东西,否则你可能会使用你得到的代码。

    【讨论】:

      【解决方案2】:

      我会这样做:

      类数组 { 民众: 大批() { 对于 (int i = 0; i

      然后您可以执行以下操作:

      数组 x; // 创建 4x4 数组 x(1, 2) = 3; // 修改元素

      【讨论】:

      • 更自然地,不应该交换 i 和 j 吗? (也许使用 x 和 y 来代替可读性。)另外,我认为复制构造函数是有序的......
      • i 和 j 是有位置的,所以你可以使用任何你想要的顺序。创建一个复制构造函数是个好主意。
      【解决方案3】:

      在传递数组时,您必须决定是否要制作数组的副本,或者是否只想返回指向数组的指针。对于返回数组,您不能(轻松)返回副本 - 您只能返回指针(或 C++ 中的引用)。例如:

      // Piece::returnPiece is a function taking no arguments and returning a pointer to a
      // 4x4 array of integers
      int (*Piece::returnPiece(void))[4][4]
      {
          // return pointer to the array
          return &pieceArray;
      }
      

      要使用它,可以这样称呼它:

      int (*arrayPtr)[4][4] = myPiece->returnPiece();
      int cell = (*arrayPtr)[i][j];  // cell now stores the contents of the (i,j)th element
      

      请注意类型声明和使用它的相似之处 - 括号、解引用运算符 * 和括号位于相同的位置。

      您对Grid::InsertArray 的声明是正确的 - 它有一个参数,即一个 4x4 整数数组。这是按值调用:无论何时调用它,都会复制 4x4 数组,因此您所做的任何修改都不会反映在传入的数组中。如果您想使用按引用调用,您可以而是传递一个指向数组的指针:

      // InsertArray takes one argument which is a pointer to a 4x4 array of integers
      void Grid::InsertArray(int (*arr)[4][4])
      {
           for(int i = 0; i < x_ROWS; i++)
           {
               for(int j = 0; j < y_COLUMNS ; j++)
                   squares[i][j] = (*arr)[i][j];
           }
      }
      

      这些带有指向多维数组的指针的类型声明很快就会变得非常混乱。我建议为它创建一个typedef,如下所示:

      // Declare IntArray4x4Ptr to be a pointer to a 4x4 array of ints
      typedef int (*IntArray4x4Ptr)[4][4];
      

      然后你可以声明你的函数更具可读性:

      IntArray4x4Ptr Piece::returnPiece(void) { ... }
      void Grid::InsertArray(IntArray4x4Ptr arr) { ... }
      

      您还可以使用cdecl 程序来帮助破译复杂的 C/C++ 类型。

      【讨论】:

      • 哇。我不知道你可以返回一个二维数组。 K&R 似乎很酷。我不得不将声明更改为: int (*returnPiece())[4] { return pieceArray; }
      • 是的。如果你想让数组衰减,你可以返回“pieceArray”而不是它的地址。将返回指向其第一个元素的指针,其类型为 int(*)[4] 。但缺点是你失去了外部尺寸的大小。我认为亚当的方法更好......
      • ...除非外部尺寸可以具有任意大小。但它的大小似乎总是 4。返回衰减数组的一个好处是你有返回的东西的自然 iindex 语法: foo()[4][4] 而不是 (*foo())[4][ 4]不再。考虑到两者,我仍然更喜欢亚当的。
      • 不,他原来的 Grid::InsertArray(int arr[4][4]) 是 Call-by-Reference。内存中只有一个数组,它是pieceArray,并且是共享的。值可以从您下方更改。对于按值调用(复制)... 结构的最佳作弊。 (我会单独发布。)
      【解决方案4】:

      Adam Rosenfield 的 arrayPtr 的问题在于,Piece::pieceArray 可能会在你的下方发生变化。 (按引用复制与按值复制。)

      按值复制效率低下。但如果你真的想做,那就作弊吧:

      struct FOO { int  piece [4][4]; };
      
      FOO Piece::returnPiece()
      {
        FOO f;
        memcpy( f.piece, pieceArray, sizeof(pieceArray) );
        return f;
      }
      
      void Grid::InsertArray( const FOO & theFoo )
      {
        // use theFoo.piece[i][j]
      }
      

      当然,更好、更面向对象的解决方案是让 returnPiece() 创建并返回一个 PieceArray目的。 (正如 Juan 建议的那样......)

      【讨论】:

      • 一般方法是 template struct wrap { T t; wrap(T const& t) { memcpy(this->t, t, sizeof t); } };模板 wrap make_wrap(T const& t) { return wrap(t); } 然后返回 make_wrap(pieceArray) 并在 InsertArray 方法中接受 wrap
      • litb:你提出了一个很好的观点。但是,为什么要泛化一个 kludge 来克服 C/C++ 无法复制数组的问题呢? make_wrap() 是不必要的。小心不要将 memcpy() 的使用泛化到包含指针的类型。鉴于 OP 的 C++ 技能,是否明智地通过模板增加编码复杂性?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-17
      • 2021-12-24
      • 2014-12-22
      • 1970-01-01
      • 2019-04-13
      相关资源
      最近更新 更多