如何从用户自定义函数返回一个三维数组?

5
我希望能从用户定义的函数中返回一个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
}

我建议使用向量,这样你就不必考虑指针了。 - Deepak Patankar
2
std::array? - Some programmer dude
假设三个维度都固定为“2”,返回一个std::array<std::array<std::array<element_type, 2>, 2>, 2> - Peter
5个回答

5

仅作为一条注释:一个 int *** 不适用于返回一个三维数组。最多只能用于返回指向指针数组的指针。

由于在 C++ 语言中原始数组不是一等元素,你不能简单自然地从函数中返回一个数组。

那么该怎么办呢?

  1. The C++ simple way:

    Do not use raw arrays but std::array is the size if fixed at compile time, or std::vector if it is not. You can then build (and return vectors of vectors or std::array of std::array. Beware a vector of vectors is like an array of pointers: the data is not required to be contiguous, so it is not equivalent to a 3D array. Here, assuming fixed sizes:

     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. A custom container (still modern C++)

    If you need to simulate a 3D contiguous container in C++ and have it to behave like a normal object (that can be returned from a function), you will have to build a custom container and its accessor methods. It is not extremely complex, yet it is far from trivial. If you want to go that way, my advice is to use a (1D) vector as the underlying storage to not be bothered with the copy, move, destruct problem with raw allocated storage.

  3. The C-ish way (with raw arrays).

    Multi-dimensional arrays must have all their dimensions but the last one defined at compile time. Once this is said, you still find the 3 common C storage ways: static storage (can be safely returned, but is not thread safe), allocated storage (thread safe, but caller will be responsable for freeing it), caller provided (the caller is responsable for creating the array and pass it to the callee function. I will show you the 3rd way here

     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;
     }
    

    Usage:

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

3
你可以使用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!
}

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;
}

2
嵌套向量的缺点是它在幕后进行指针解引用。对于三维向量,这意味着它必须解引用3个指针。这比使用一维向量并使用一些算术将3个索引转换为一个偏移量更低效。因此,在这种情况下,它可能看起来像:std::vector vec(2 * 2 * 2); ...; vec[i + 2 * (j + 2 * k)] = a[i] * b[j] * c[k]; - G. Sliepen
1
除非您在循环之前设置维度(外向量及递归包含的向量),否则您的示例函数将具有未定义的行为。vector 的 operator[] 无法确保所提供的索引是有效的。 - Peter

1
正如其他人提到的那样,您可以使用 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
}

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数组函数返回一个二维数组,3d数组函数返回一个三维数组。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接