如何从用户定义的函数返回 3D 数组?

Posted

技术标签:

【中文标题】如何从用户定义的函数返回 3D 数组?【英文标题】:How to return a 3D array from user defined function? 【发布时间】: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

【问题讨论】:

我建议使用向量,使用它你不必考虑指针。 std::array? 假设三个维度都固定为2,返回一个std::array&lt;std::array&lt;std::array&lt;element_type, 2&gt;, 2&gt;, 2&gt; 【参考方案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++ 语言中的第一类元素,因此您不能以简单自然的方式从函数返回数组。

可以做什么?

    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;
     
    

    自定义容器(仍然是现代 C++)

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

    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!

【讨论】:

以上是关于如何从用户定义的函数返回 3D 数组?的主要内容,如果未能解决你的问题,请参考以下文章

awk 问题(从用户定义的函数返回一个数组)

如何从 SQL 中的用户定义函数返回多个值

如何从函数返回动态分配的指针数组?

如何从matlab中用户定义的函数返回一个值,该函数的回调在uicontrol中指定

如何在用户定义的函数中将数据库列作为参数传递?

函数如何将数组或设置值作为 PostgreSQL 中用户定义函数的参数 (IN)