【问题标题】:C++ - Return multidimensional array from functionC++ - 从函数返回多维数组
【发布时间】:2014-07-23 00:42:13
【问题描述】:

我正在为元胞自动机编写代码,我需要一个进化函数来计算时间步后自动机的状态。 我选择将此函数称为 evol,为了测试它,我在 C++ 中创建了一个基本函数。不幸的是,它无法编译,因为编译器无法理解我需要它来返回一个数组。这是代码:

#include <iostream>
#include <cmath>
#include <vector>
#include <string>

using namespace std;

const int N = 51; // Size of the grid; two columns/rows are added at the beginning and the end of the array (no evolution of the CA on the boundaries)

class Cell{
    //defining whats a cell here        
};

void showCA(Cell CA[N+2][N+2]){
    //function to print the CA grid in the terminal         
}


Cell[N+2][N+2] evol(Cell CA[N+2][N+2]){
    return CA;
}

int main()
{
     // Initialisation
    cout << "Initialisation" << endl;
    static Cell CA[N+2][N+2];
    // some code here to initialize properly the Cell array.
    showCA(CA);
    CA = evol(CA);
    showCA(CA);
    return 0;
} 

编译器返回此错误:

error: expected unqualified-id
Cell[N+2][N+2] evol(Cell CA[N+2][N+2]){

关于我应该如何实现它的任何想法?

【问题讨论】:

  • 使用分号来修复该错误。您可能也想使用向量。
  • N 究竟代表什么?您的代码中有许多奇怪的语句。你最终想达到什么目标?
  • 创建一个类来表示一个多维数组(可能作为一个包装器来提供二维寻址到std::vector)。返回该类的一个实例。
  • 过去几十年的标准方法是提供一个目标数组作为 evol 的参数,它不会返回任何内容或可能返回 bool,表示成功。调用者可能会有两个数组,它们在每次进化后将角色交换为源和目标。
  • 您声明返回数组的函数的语法不正确。使用Cell evol(Cell CA[N+2][N+2])[N+2][N+2] 而不是Cell[N+2][N+2] evol(Cell CA[N+2][N+2]) 可以获得更有用的错误消息。

标签: c++ function multidimensional-array


【解决方案1】:

你可以使用

typedef std::vector<std::vector<Cell>> CellArray;
CellArray Cells(N+2);  // resize main dimension
for (size_t i=0; i<N+2; i++)
    Cells[i].resize(N+2); // resize all cells of main dimension

保存您的元胞数组,但您还需要在 Cell 类中添加一个复制构造函数和 operator=

class Cell {
public:
    Cell() { ... default ctor code here ... }
    Cell(const Cell &c) { *this = c; }

    Cell &operator=(const Cell&c)
    {
        if (this != &c)
        {
            ... copy data from c members to this members here ...
        }
        return *this;
    }
};

然后你的 evol 函数可以返回一个 CellArray:

CellArray evol(CellArray &c)
{
   CellArray r;
   ... do some calculations with c and r ...
   return r;
}

【讨论】:

  • 你不需要移动 ctor 吗?也许,为了避免给你的继任者带来有趣的惊喜,搬家任务?这一切听起来几乎是荒谬的矫枉过正。
  • @PeterSchneider 这里没有什么可以移动的(RVO)。但是,如果一个类可以移动复制和移动分配是有意义的,它应该允许这些操作。
【解决方案2】:

一旦你像你一样使用数组语法声明了一个变量:

Cell CA[N+2][N+2];

您不能将CA 指定为其他内容。您只能为其内容赋值。因此,

CA = evol(CA);

错了。

您可以执行以下操作:

Cell (*CA2)[N+2] = evol(CA);

【讨论】:

    【解决方案3】:

    由于元素的数量似乎是固定的,我建议你使用std::array容器:

    const int N = 51;
    typedef std::array<std::array<Cell,N+2>, N+2> datatype;
    

    然后您可以将此类型用作返回类型:

    datatype Evol( const datatype& d );
    

    您可以像访问“C”数组一样访问元素:

    datatype d;
    Cell c;
    d[10][20] = c;
    

    【讨论】:

      【解决方案4】:

      您不能从函数中返回数组:

      § 8.3.5/8

      函数不应具有数组或函数类型的返回类型,尽管它们可能具有指针类型或对此类事物的引用的返回类型。

      如果您希望从函数返回原始的 C 样式数组,那么您必须使用引用或指针。例如,下面是使用引用的方法(您可以使用指针,将&amp; 替换为*):

      Cell (&evol(Cell (&CA)[N+2][N+2]))[N+2][N+2];
      

      但是,这是非常不直观且难以阅读的。如果您的编译器支持最新标准 (C++11),则可以使用尾随返回类型清除返回类型:

      auto evol(Cell (&CA)[N+2][N+2]) -> Cell(&)[N+2][N+2];
      

      但同样,这可能仍然难以阅读。


      C++11 便于使用容器std::array&lt;&gt; 处理 C 样式数组。非 C++11 代码应该使用std::vector&lt;&gt;:

      using Cells = std::array<std::array<Cell, N+2>, N+2>;
      
      Cells const& evol(Cells const& CA);
      

      【讨论】:

      • 如果数组很大,返回一个 std::array 可能效率低下或危险(因为,你猜,堆栈溢出)。
      • @PeterSchneider 我怀疑std::array 会比常规数组有更多开销。在任何情况下,使用数组与std::array 时潜在堆栈溢出的大小完全相同,在这种情况下应该使用std::vector
      • 关于溢出为真;但是返回一个 std::array 只是复制了很多字节,不是吗(而不是返回一个指针或一个带有移动语义的 std::vector)。
      • 此外,如果您返回对 C 数组的引用,最好不要将它放在堆栈中。
      • @PeterSchneider 按值返回数组没有问题。副本将被省略。 如果无论出于何种原因(外来 C++ 实现/平台、准标准编译器等)都没有省略它。那么人们可以开始思考解决该问题的巧妙方法。
      【解决方案5】:

      我强烈建议将您的数组封装到一个类中。不能返回数组,但可以返回包含数组的对象。

      【讨论】:

        猜你喜欢
        • 2018-01-05
        • 2017-03-06
        • 2021-03-29
        • 2012-12-08
        • 1970-01-01
        • 2011-07-20
        • 2021-05-01
        • 2021-12-04
        相关资源
        最近更新 更多