我有我想花作为参数,可变大小的二维数组的函数。

到目前为止我有这︰

void myFunction(double** myArray){
     myArray[x][y] = 5;
     etc...
}

并且我有我的代码中其他位置声明数组︰

double anArray[10][10];

但是,调用myFunction(anArray)给了我一个错误。

我不想当我传递复制数组。myFunction中所做的任何更改应改变anArray的状态。如果我理解正确,我只想在作为参数传递一个指针到一个二维数组。此函数需要也接受不同大小的数组。例如, [10][10][5][5]如何执行此操作?

2012-01-07 03:40:31
问题评论:

您得到了什么错误?

无法将参数 3 从双 [10] [10] 转换为双 * *

声明为 anArray"双 * anArray [10]"将对其进行编译好的但只要我知道 [10] [10] 和 * [10] 应相同。我不知道两者之间细微的差别。:(

[其(2)(3)是相同的]接受答案显示仅 2 技术,但还有4 种唯一传递到函数的二维数组.

已接受的答案只显示 1 种传递一个二维数组。2 和 3 的情况下不是二维数组,因此我看不到它们是更相关。

回答:

有三种方法可以将二维数组传递给一个函数︰

  1. 参数是一个二维数组

    int array[10][10];
    void passFunc(int a[][10])
    {
        // ...
    }
    passFunc(array);
    
  2. 该参数是一个数组,包含指针

    int *array[10];
    for(int i = 0; i < 10; i++)
        array[i] = new int[10];
    void passFunc(int *a[10]) //Array containing pointers
    {
        // ...
    }
    passFunc(array);
    
  3. 该参数是一个指针,指向的指针

    int **array;
    array = new int *[10];
    for(int i = 0; i <10; i++)
        array[i] = new int[10];
    void passFunc(int **a)
    {
        // ...
    }
    passFunc(array);
    

所有的好答案,谢谢您。我选择这个我都相信我要查找的示例 3) 示

@Overflowh 可以获取的元素的arrayarray[i][j] :)

对于第一种情况下,该参数可声明为int (*a)[10].

对于第二种情况下,该参数可声明为int **.

2 和 3 的情况下不是二维数组,因此此答案是有误导性。看到这一点.

固定的大小

1.通过引用传递

template <size_t rows, size_t cols>
void process_2d_array_template(int (&array)[rows][cols])
{
    std::cout << __func__ << std::endl;
    for (size_t i = 0; i < rows; ++i)
    {
        std::cout << i << ": ";
        for (size_t j = 0; j < cols; ++j)
            std::cout << array[i][j] << '	';
        std::cout << std::endl;
    }
}

在 c + + 通过引用传递该数组,而不会丢失该维度信息是可能最安全的方法,因为一个不必担心调用方传递不正确的尺寸 (编译器标志不匹配时)。但是,这不可能与动态 (freestore) 阵列;它适用于即只应在编译时已知维数的自动 (通常是堆栈生活) 数组。

2.通过指针传递

void process_2d_array_pointer(int (*array)[5][10])
{
    std::cout << __func__ << std::endl;
    for (size_t i = 0; i < 5; ++i)
    {
        std::cout << i << ": ";
        for (size_t j = 0; j < 10; ++j)
            std::cout << (*array)[i][j] << '	';
        std::cout << std::endl;
    }    
}

C 相当于前一种方法通过指针传递数组。这不应与传递数组的发生衰变指针类型(3),这是最常见、 流行的方法,即使是小于此比安全但更灵活的混淆。(1),如使用此方法时该数组的所有维度是固定的在编译时已知。请注意,在调用该函数数组的地址应传递process_2d_array_pointer(&a)并不是第一个元素的地址由衰变process_2d_array_pointer(a).

可变大小

这些从 C 继承,但不太安全,编译器将无法检查,确保调用方传递所需的尺寸。该函数只银行上调用方作为维度传送的内容。由于不同长度的数组可以被传递给它们总是,这些都是比上述更灵活。

它是要记住,没有将数组传递给一个函数在 C [在 c + + 中他们可以作为一个参考(1)]; 直接没有这样的内容(2)将指针传递给的数组,该数组中。始终通过为数组的是成为得益于阵列的性质衰变为一个指针,该指针复制操作.

3.通过 (值) 将指针传递给 decayed 的类型

// int array[][10] is just fancy notation for the same thing
void process_2d_array(int (*array)[10], size_t rows)
{
    std::cout << __func__ << std::endl;
    for (size_t i = 0; i < rows; ++i)
    {
        std::cout << i << ": ";
        for (size_t j = 0; j < 10; ++j)
            std::cout << array[i][j] << '	';
        std::cout << std::endl;
    }
}

int array[][10]允许的虽然我不建议它通过以上语法因为上面的语法可以清楚地标识符array是一个指针到 10 的整数,而此语法看起来像它的数组是二维数组,但已到 10 的整数的数组相同的指针。这里我们知道单个行 (即列大小,这里 10) 中的元素数目但行数未知,因此可作为参数传递。在这种情况下没有某些安全由于具有不等于 10 的第二个维度的数组的指针传递时,可以标记编译器。第一个维度是不同的一部分,则可以省略。这里看到的基本原理只有第一个维度允许被忽略。

4.通过传递指针指针

// int *array[10] is just fancy notation for the same thing
void process_pointer_2_pointer(int **array, size_t rows, size_t cols)
{
    std::cout << __func__ << std::endl;
    for (size_t i = 0; i < rows; ++i)
    {
        std::cout << i << ": ";
        for (size_t j = 0; j < cols; ++j)
            std::cout << array[i][j] << '	';
        std::cout << std::endl;
    }
}

再没有其他的语法int *array[10]即相同int **array在此语法中[10]被忽略,因为它从而成为一个指针到衰减int **array也许它是只向调用方传递的数组应具有至少 10 列,甚至,则行计数是所需的提示。在任何情况下,编译器不标记任何长度/大小冲突 (它只检查是否传递的类型是指向指针的指针),因此需要行和列统计参数这里意义一样。

注意︰(4) 是最安全的选项因为它几乎不具有任何类型检查和最不方便。合法,一个能将二维数组传递给此函数;C 常见问题解答 condemns做的常规解决方法int x[5][10]; process_pointer_2_pointer((int**)&x[0][0], 5, 10);因为它由于平面阵列化有可能导致未定义的行为在此方法中传递数组的正确的方式引出了我们的方便的一部分即我们需要额外的 (代理) 的指针数组与每个它指向各自的实际,要传递的数组; 如果行的元素此代理然后传递给函数 (见下文);所有这些用于获取同一上面的方法,它是更安全、 更整洁和可能更快地完成工作。

下面是驱动程序来测试上面的函数︰

#include <iostream>

// copy above functions here

int main()
{
    int a[5][10] = { { } };
    process_2d_array_template(a);
    process_2d_array_pointer(&a);    // <-- notice the unusual usage of addressof (&) operator on an array
    process_2d_array(a, 5);
    // works since a's first dimension decays into a pointer thereby becoming int (*)[10]

    int *b[5];  // surrogate
    for (size_t i = 0; i < 5; ++i)
    {
        b[i] = a[i];
    }
    // another popular way to define b: here the 2D arrays dims may be non-const, runtime var
    // int **b = new int*[5];
    // for (size_t i = 0; i < 5; ++i) b[i] = new int[10];
    process_pointer_2_pointer(b, 5, 10);
    // process_2d_array(b, 5);
    // doesn't work since b's first dimension decays into a pointer thereby becoming int**
}

谢谢您先生现在作为引用传递多维数组适合我 !

怎样通过动态分配到 c + + 中的函数的数组?C11 中标准的静态和动态分配来完成类似的阵列 fn (int 列,int 行 int array[col][row]): stackoverflow.com/questions/16004668/...我做这一问题的问题︰ stackoverflow.com/questions/27457076/...

@42n4 例 4 介绍了 (对于 c + + 以及) 的。对于动态分配数组,只是在循环内的行更改从b[i] = a[i];b[i] = new int[10];一个还会使b动态分配int **b = int *[5]; ,它仍然会工作为的是。

寻址array[i][j]的工作方式中的函数为4)因为它已经收到 ptr 指针并不知道这是正确解决执行班次所需的最后一个维度的值?

array[i][j]不仅仅是指针算法即为指针array的值,它将添加i的取消引用和结果为int*,它会向其添加j和取消引用该位置,读取一个int所以,不,它不一定为此知道任何维度。但这只是整个点 !编译器将程序员的 word 中的信仰和程序员是不正确的如果未定义的行为,才会进行。这就是我先前提到,4 例是最安全的选项的原因。

对 shengy 的第一个建议的修改,您可以使用模板以使函数接受一个多维数组变量 (而不是存储的需要进行管理和删除的指针的数组)︰

template <size_t size_x, size_t size_y>
void func(double (&arr)[size_x][size_y])
{
    printf("%p
", &arr);
}

int main()
{
    double a1[10][10];
    double a2[5][5];

    printf("%p
%p

", &a1, &a2);
    func(a1);
    func(a2);

    return 0;
}

打印语句的目的是为了显示,获取数组按引用传递 (通过显示变量的地址)

应打印指针,使用%p ,即使如此,您必须将其强制转换为void *,其他printf()调用未定义的行为。此外,您不应使用 addressof (&) 运算符时调用这些函数,因为函数期望为参数的类型double (*)[size_y],而目前传递它们double (*)[10][10]double (*)[5][5].

如果使用模板制作两个维度为模板参数更合适,是更好,因为可以完全避免低级指针访问。

您可以创建这样一个函数模板︰

template<int R, int C>
void myFunction(double (&myArray)[R][C])
{
    myArray[x][y] = 5;
    etc...
}

然后,您可以通过 R 和 c。 这两个维度的大小不同的函数将创建为每个数组的大小,因此如果您的函数很大并且调用具有不同的数组大小的不同,这可能代价高昂。您可以使用它作为包装如下函数不过︰

void myFunction(double * arr, int R, int C)
{
    arr[x * C + y] = 5;
    etc...
}

它将数组视为一维,并使用算法算出的索引的偏移量。在这种情况下,您需要定义的模板如下︰

template<int C, int R>
void myFunction(double (&myArray)[R][C])
{
    myFunction(*myArray, R, C);
}

size_t是比int数组索引的好类型.

anArray[10][10]不是指向指针的的指针,它是连续内存区块适用于存储 100 个 double 类型的值的编译器知道如何解决因为指定尺寸。您需要将其传递到一个函数作为数组。可以省略初始尺寸,的大小,如下所示︰

void f(double p[][10]) {
}

但是,这将不允许您传递数组最后一个维度以外的其他 10 个。

在 c + + 的最佳解决方案是使用std::vector<std::vector<double> >︰ 它是几乎一样有效,并且显著更方便。

我更喜欢标准库此解决方案非常有效-顺便说一句我喜欢 dasblinkenlight;用于使用 dasblikenlicht

几乎一样有效吗?是的右侧。指针追踪始终是更多比非指针追高。

内容来源于Stack Overflow Passing a 2D array to a C++ function
请输入您的翻译

Passing a 2D array to a C++ function

确认取消