【问题标题】:How to return a 3D array from user defined function?如何从用户定义的函数返回 3D 数组?
【发布时间】:2020-11-15 02:49:27
【问题描述】:

我想将用户定义函数中的 3 维数组返回到我的 main 函数中。

让我们考虑一个简单的例子,用于 abc 数组的任何特定值;

int*** my_function(int a[], int b[], int c[])
{
   for (int i = 0; i < 2; i++)
   {
      for (int j; j < 2; j++)
      {
         for (int k; k < 2; k++)
         {
            array[i][j][k] = a[i] * b[j] * c[k];
         }
      }
   }
   return array
}

【问题讨论】:

  • 我建议使用向量,使用它你不必考虑指针。
  • 假设三个维度都固定为2,返回一个std::array&lt;std::array&lt;std::array&lt;element_type, 2&gt;, 2&gt;, 2&gt;

标签: c++ arrays function c++11 multidimensional-array


【解决方案1】:

我已经得到了你想要的东西

#include <iostream>
using namespace std;

int** form_2d_array(int l, int b)
{
    int **A = new int *[b];
    for (int i = 0; i < b; i++)
        A[i] = new int[l];
    return A;
}

int*** form_3d_array(int l, int b, int h)
{
    int ***A = new int **[h];
    for (int i = 0; i < h; i++)
        A[i] = form_2d_array(l,b);
    return A;
}

int main()
{
    int ***array;
    int l,b,h;
    l=3;b=5;h=3;
    array=form_3d_array(l,b,h);
    for (int i = 0; i < l; i++)
    {
        for (int j=0; j < b; j++)
        {
            for (int k=0; k < h; k++)
            {
                array[i][j][k] = i+j+k;
            }
        }
    }
    for (int k=0; k < h; k++)
    {
        cout<<"Printing "<<k+1<<"th matrix\n";
        for (int i = 0; i < l; i++)
        {
            for (int j=0; j < b; j++)
            {
                cout<<array[i][j][k]<<" ";
            }
            cout<<endl;
        }
        cout<<endl;
    }
    
    return 0;
}

2d 数组函数返回一个 2d 数组,3d 数组函数返回一个 3d 数组。

【讨论】:

    【解决方案2】:

    使用指针的更好替代方法是使用std::vector,因为它会处理内存分配和释放的细节。

    如何初始化 3D 矢量?

    3D 向量只是一个包含两个其他向量的向量。所以,如果你想用值 A 初始化一个大小为 X * Y * Z 的 3D 向量。那么它可以这样做:

    vector<vector<vector<int> > > vec (X,vector<vector<int> >(Y,vector <int>(Z,A)))
    

    如何从函数中返回它?

    您可以从下面的示例中看到如何返回它。

    vector<vector<vector<int> > >  sample_function()
    {
    
         //sample code
    
    return vec;
    }
    

    【讨论】:

    • 嵌套向量的缺点是它在后台进行指针解引用。对于 3D 向量,这意味着它必须取消引用 3 个指针。这比拥有一维向量并使用一些算术将 3 个索引转换为一维向量的一个偏移量效率低。所以在这种情况下,它可能看起来像:std::vector vec(2 * 2 * 2); ...; vec[i + 2 * (j + 2 * k)] = a[i] * b[j] * c[k];
    • 您的示例函数将具有未定义的行为,除非您在循环之前设置(外部向量以及递归地包含向量的)维度。 vectors operator[] 不能确保提供的索引有效。
    【解决方案3】:

    请注意:int *** 不适合返回 3D 数组。最多可以用来返回一个指向指针数组的指针。

    由于原始数组不是 C++ 语言中的第一类元素,因此您不能以简单自然的方式从函数返回数组。

    可以做什么?

    1. C++ 简单方法:

      不要使用原始数组,但std::array 是在编译时固定的大小,或者std::vector 如果不是。然后,您可以构建(并返回向量的向量或std::arraystd::array。请注意向量向量就像一个指针数组:数据不需要是连续的,因此它不等同于 3D 数组。这里,假设固定大小:

       std::array<std::array<std::array<int, 2>, 2>, 2> my_function(int a[], int b[], int c[])
       {
         std::array<std::array<std::array<int, 2>, 2>, 2> array;
         ...
         return array;
       }
      
    2. 自定义容器(仍然是现代 C++)

      如果您需要在 C++ 中模拟一个 3D 连续容器并让它表现得像一个普通对象(可以从函数返回),您将必须构建一个自定义容器及其访问器方法。它不是非常复杂,但远非微不足道。如果你想这样做,我的建议是使用 (1D) 向量作为底层存储,以免被原始分配存储的复制、移动、破坏问题所困扰。

    3. C-ish 方式(使用原始数组)。

      多维数组必须具有所有维度,但最后一个维度是在编译时定义的。说了这么多,你还是会找到 3 种常见的 C 存储方式:静态存储(可以安全返回,但不是线程安全的)、分配存储(线程安全,但调用者将负责释放它)、调用者提供( caller 负责创建数组并将其传递给被调用函数。我将在这里向您展示第三种方式

       typedef int (*int3D)[2][2];
      
       int3D my_function(int a[], int b[], int c[], int3D array) {
       {
         for(int i=0; i<2; i++)
         {
           ...
         }
         return array;
       }
      

      用法:

       int arr[2][2][2];
      
       int3D arr3D = my_function(a, b, c, arr);
       // after the call, arr3D == arr is true
      

    【讨论】:

      【解决方案4】:

      正如其他人提到的,您可以使用std::arraystd::vector,但一种简单的方法是将数组作为参数传递给您的函数(而不是返回)。像这样的……

      void your_function(int array[2][2][2], /* other parameters */) {
          // body
      }
      

      并像这样使用它:

      int main() {
          int arr[2][2][2];
          your_function(arr, /* other arguments */);
          // now do what you want with arr
      }
      

      【讨论】:

        【解决方案5】:

        您可以使用std::array

        如果大小是已知的编译时间,我建议使用std::array,通过它您可以获得连续的内存布局。

        #include <iostream>
        #include <array>
        #include <algorithm> // std::generate
        
        // alias for the required array
        using Array3D = std::array<std::array<std::array<int, 2>, 2>, 2 >;
        
        Array3D func()
        {
           Array3D arr3d;
           std::array<int, 2> a{ 10, 20 }, b{ 10, 20 }, c{ 10, 20 }; // some a, b, c
        
        
           // iterate through the arrays to initialize them!
           auto input = 1u;
           for (std::array<std::array<int, 2>, 2> & array2D : arr3d) // or auto& array2D: arr3d
              for (std::array<int, 2> & arr : array2D)                // or auto& arr: array2D
                 std::generate(arr.begin(), arr.end(), [&input] { return input++; });
        
           // for array multimplications!
           for (std::array<std::array<int, 2>, 2> & array2D : arr3d) // or auto& array2D
           {
              for (std::array<int, 2> & arr : array2D)               // or auto& arr
              {
                 auto arrIndex = 0u;
                 for (int& ele : arr)
                 {
                    ele = a[arrIndex] * b[arrIndex] * c[arrIndex];
                    ++arrIndex;
                    std::cout << ele << " "; // to print the element!
                 }
              }
           }
        
           return arr3d; // return the array like this!
        }
        

        或者使用模板函数(将大小作为非模板参数),您甚至可以通过引用传递array3d 并按照上面显示的方式进行计算!

        #include <iostream>
        
        template<std::size_t M, std::size_t N, std::size_t O>
        void func(int (&arr3d)[M][N][O])
        {
           // some a, b, c
        
           for (std::size_t i = 0; i < M; ++i)
           {
              for (std::size_t j = 0; j < N; ++j)  
              {
                 for (std::size_t k = 0; k < O; ++k)
                 {
                    arr3d[i][j][k] = a[k] * b[k] * c[k];
                    std::cout << arr3d[i][j][k] << " "; // to print the element
                 }
                 std::cout << "\n";
              }
              std::cout << "\n";
           }
           // do not need to return!
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-06-07
          • 2012-09-03
          • 2021-12-22
          • 2014-09-14
          • 1970-01-01
          • 1970-01-01
          • 2019-09-11
          • 1970-01-01
          相关资源
          最近更新 更多