如何使用三重指针传递3D数组?

时间:2019-06-12 05:03:07

标签: c++ arrays pointers

真的有可能吗?

我知道如何使用双指针传递二维数组。根据我的理解,它也应该适用于3-D阵列。但是我很想被证明是错误的。这个问题肯定会揭示如何解释数组。

这里的事实是3-D数组是一个连续的块,而不是一些较小块的指针数组。

该程序给我错误:

#include <iostream>

using namespace std;

void display(int ***arr, int l, int m, int n)
{
    for(int i=0; i<l; i++)
        for(int j=0; j<m; j++)
            for(int k=0; k<n; k++)
                cout << *(*(*(arr+i)+j)+k) << endl;
}

int main()
{
    int arr[][2][2] = {{{1,2},{3,4}},{{10,20},{30,40}}};
    display((int***)arr,2,2,2);
}

输出

test.cpp:17:19: error: cannot convert 'int (*)[2][2]' to 'int***' for argument '1' to 'void display(int***, int, int, int)'
  display(arr,2,2,2);
                   ^

二维数组传递给双指针 我相信我也可以做类似于3D阵列的事情,但这太糟了,难以阅读。

#include <iostream>

using namespace std;

void display(int **arr, int m, int n)
{
    for(int i=0; i<m; i++)
        for(int j=0; j<n; j++)
            cout << *(*(arr+i)+j) << " " << arr[i][j] << endl;
}

int main()
{
    int arr[][3] = {{1,2,3},{4,5,6}};
    int *temp[2];
    for(int i=0; i<2; i++)
        temp[i] = *(arr+i);
    display(temp,2,3);
}
OUTPUT
1 1
2 2
3 3
4 4
5 5
6 6

4 个答案:

答案 0 :(得分:1)

您对2D数组所做的操作是正确的,因为您已经构建了一个辅助指针数组,并且将该指针数组作为int **进行了传递。即使对于2D阵列,这

void display(int **arr, int m, int n);
...

int arr[][3] = {{1,2,3},{4,5,6}};
display(arr,2,3);            // WRONG! use a 2D array as an array of pointers

会错的。

无论如何,C ++标准对多维数组并不友好:无法编写传递未知维的多维数组的严格一致的程序。许多编译器都接受它作为扩展,但是它在其他编译器上可能无法移植。

惯用的方法是仅将一维数组用作基础数据结构,并通过内部进行索引计算来提供将其作为多维容器处理的方法。


顺便说一句,我尝试构建一个具有任意运行时维度的多维连续容器,同时尊重标准容器的所有约束,并在意识到该标准不允许之后放弃了:不可能构建一个对不保存自己数据的对象进行 nice 迭代。这是我最好的attempt。答案和评论解释了为什么它没有希望。

答案 1 :(得分:0)

尽管您可以像这样传递一维数组

$ clang++-7 -g -O3 -std=c++2a locking.cpp -o locking && ./locking 
Starting test
  With lock took 2099204ns
    No lock took 2126724ns
Atomic lock took 12922543ns

实际上,编译器会将void pass1Darray(int a[]) { statements; } int main() { int a[10]; pass1Darray(a); } 视为int a[],这就是人们怀疑是否有可能通过pointer_to_pointer传递二维数组的原因。

但这没有意义!

如果要传递2D数组int* a,则可以将bob视为一个数组,并且其元素是一个数组,并像这样传递它

bob[5][10]

这是关于传递二维数组。

顺便说一句,英语不是我的母语,而且我也是c ++的初学者。

如果出问题了,请告诉我,谢谢。

答案 2 :(得分:0)

在本地int arr[][2][2]声明数组时,编译器将实例化一维向量,并“记住”偏移量以获取正确的索引。

本地数组也存储在堆栈中,如果您需要大型矩阵,则这不是很好。 int arr[][2][2]的另一个特性是为什么当您尝试将其作为参数传递给函数时,int arr [] [2] [2] 类型。您必须指定所有尺寸。

指针的工作方式不同。如果实例化2D数组,则需要为行分配一个指针数组,并分配每个行数组以分别保存数据。在C ++中,我认为最好使用标准库,该库具有动态指针的标准实现,该指针负责所有分配。 std::vector

结论:

  • 当所需的内存很小并且不需要使用指针时,我将使用局部数组。如果要避免使用堆,则使用本地数组是很好的选择。
  • 允许使用指针new / delete或malloc / free,但我认为最好使用C ++中的标准库,因此在所有其他情况下我都将使用std :: vector。

答案 3 :(得分:0)

  

我相信我也可以做类似于3D阵列的事情,但这太糟糕了,难以阅读。

是的,正如n.m.在其评论中解释的那样

  

在2D代码中,您创建了一个全新的指针数组,将其填充,然后将其传递给函数,而不是原始的2D数组。在您的3D代码中,您没有尝试任何类似的操作。

由于该问题被标记为C ++,因此我们可以使用与C编码人员不同的工具箱。

在C ++中,不仅可以通过值,还可以通过 reference 将参数传递给函数,并且我们可以编写 template ,编译器可以使用该模板来为使用的类型生成正确的函数。

#include <iostream>
#include <iomanip>

template <class T, size_t L, size_t M, size_t N>
void display( T const (&arr)[L][M][N], int width )
//                    ^^^^^^
{
    for (size_t i = 0; i < L; ++i) {
        for (size_t j = 0; j < M; ++j) {
            for (size_t k = 0; k < N; ++k) {
                std::cout << std::setw(width) << arr[i][j][k];
            }
            std::cout << '\n';
        }
        std::cout << '\n';
    }
}

int main()
{
    int arr[3][2][4] = {
        { {1,2,3,4},
          {5,6,7,8}
        },
        { {10,20,30,40},
          {50,60,70,80}
        },
        { {100,200,300,400},
          {500,600,700,800}
        }
    };

    display(arr, 5);
}

实时HERE

当然,下一步将是编写一个封装多维数组概念的类。