【问题标题】:2D arrays with C++使用 C++ 的二维数组
【发布时间】:2009-08-16 22:08:42
【问题描述】:

我有一个函数,它将指向指针的指针作为参数。

func(double **arr, int i);

在main函数中数组的定义如下:

double arr[][] = //some initialization here;

如何从我的主代码中调用此函数。我尝试了以下但它给出了一个错误

func (&arr);

不起作用。任何帮助将非常感激。 谢谢

【问题讨论】:

    标签: c++ multidimensional-array


    【解决方案1】:

    arr 的类型是 double[X][Y] - 即 Y 双精度的 X 数组的数组 - 其中 XY 取决于您的初始化程序。这与指针类型相同。但是,根据 C 转换规则,数组可以衰减为指向其元素的指针。在您的情况下,这种衰减产生的类型将是 double(*)[Y] - 指向 Y 双精度数组的指针。请注意,这是一个指向数组的指针,而不是一个指针数组,因此它不会进一步衰减。此时,您会遇到类型不匹配,因为您的函数需要 double**

    处理这个问题的正确方法是将数组视为一维的,并传递宽度。所以:

    void func(double* arr, int w) {
       // arr[2][3]
       arr[2*w + 3] = ...;
    }
    
    
    double x[6][8] = { ... };
    func(&x[0][0], 8);
    

    特别是在 C++ 中,如果您总是静态分配已知(但不同)类型的数组,您可以使用这样的模板和引用:

    template <int W, int H>
    inline void func(const double (&arr)[W][H]) {
      arr[2][3] = ...;
    }
    
    double x[6][8] = { ... };
    func(x); // W and H are deduced automatically
    

    但是,当您只有一个指针时(例如,当数组是 new-allocated,并且它的大小是在运行时计算时),这将不起作用。对于最一般的情况,您应该改用 C++ 容器。仅在标准库中,通常使用向量的向量:

    #include <vector>
    
    void func(std::vector<std::vector<double> > arr) {
      arr[2][3] = ...;
    }
    
    std::vector<std::vector<double> > x(6, std::vector<double>(8));
    x[0][0] = ...;
    ...
    func(x);
    

    如果你可以使用 Boost,它里面有一个非常好的 MultiArray 库:

    void func(boost::multi_array<double, 2> arr) { // 2 means "2-dimensional"
      arr[2][3] = ...;
    }
    
    boost::multi_array<double, 2> x(boost::extents[6][8]);
    x[0][0] = ...;
    ...
    func(x);
    

    [EDIT] 你说你不能改变你的函数的定义。如果是这样,那么它确实是将其参数视为指针数组的函数,因此您应该相应地分配数据结构。例如:

    double x1[8] = { 1, 2, ... };
    double x2[8] = { 3, 4, ... };
    ...
    double* x[6] = { x1, x2, ... };
    
    func(x);
    

    【讨论】:

    • 漂亮而全面。但是,如果您无法更改 fn 怎么办?只需将其包装起来,使顶级数组数组是堆栈本地的(堆栈分配或异常安全堆)。也就是说,二维数组本身包含连续的一维数组,你可以直接指向它们。
    • 另外,您可以对一堆单独的一维数组使用漂亮的初始化语法并指向它们。数组初始值设定项语法仅在顶级范围内可用,对吧?
    • 好点,我会编辑。数组初始化器在任何范围(包括本地/自动)中都可用,但在 new 中不可用。
    【解决方案2】:

    double **pdouble[][] a 不同,因此您不能将一个传递给另一个。

    特别是二维数组变量是一个(单个!)内存块,其中包含您可以使用[][] 语法访问的双精度数。这要求编译器知道数组的维度,以便它可以计算每个元素的正确偏移量。它也可以透明地衰减为指向该内存块的指针,但是这样做会失去对如何以二维数组的形式访问该内存的理解:它实际上变成了指向 double 的指针。

    +----+           +---------+---------+---------+
    | (a---------->) | a[0][0] | a[0][1] | a[0][2] | ...
    +----+           +---------+---------+---------+ 
                     | a[1][0] | a[1][2] | ...
                     +---------+---------+
                       ...
    

    函数期望的是一个指向内存块的指针,其中包含一个或多个指向包含双精度值的其他内存块的指针。

    +---+       +------+      +---------+---------+
    | p-------->| p[0]------->| p[0][0] | p[0][3] | ...
    +---+       +------+      +---------+---------+
                | p[1]--\    
                +------+ \    +---------+---------+
                 ...      --->| p[1][0] | p[1][4] | ...
                              +---------+---------+
    

    虽然语法看起来很相似,但这两种结构的语义完全不同。


    如需更完整的讨论,请参阅 my answerprevious questions(实际上是针对 c,但问题相同)。

    【讨论】:

    • 那么我如何将数组传递给我的函数?我很困惑。我想将它传递给 func 而不更改其声明。
    【解决方案3】:
    func(double *arr[100])
    

    您需要告诉编译器维度的大小,以便它可以创建正确的地址

      arr[y][x]
    

    变成

      arr[100*x+y]
    

    如果你将你的函数定义为 func(double **a) 那么你就是在说一个指向指针数组的指针,正如 dmckee 指出的那样

    【讨论】:

      猜你喜欢
      • 2013-11-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-23
      相关资源
      最近更新 更多