C++ 将未知大小的数组传递给函数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3991057/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 14:13:21  来源:igfitidea点击:

Passing array with unknown size to function

c++arrays

提问by Pieter

Let's say I have a function called MyFunction(int myArray[][])that does some array manipulations.

假设我有一个调用的函数MyFunction(int myArray[][])来执行一些数组操作。

If I write the parameter list like that, the compiler will complain that it needs to know the size of the array at compile time. Is there a way to rewrite the parameter list so that I can pass an array with any size to the function?

如果我这样写参数列表,编译器会抱怨它在编译时需要知道数组的大小。有没有办法重写参数列表,以便我可以将任意大小的数组传递给函数?

My array's size is defined by two static const ints in a class, but the compiler won't accept something like MyFunction(int myArray[Board::ROWS][Board::COLS]).

我的数组的大小由static const int一个类中的两个s定义,但编译器不会接受类似MyFunction(int myArray[Board::ROWS][Board::COLS]).

What if I could convert the array to a vector and then pass the vector to MyFunction? Is there a one-line conversion that I can use or do I have to do the conversion manually?

如果我可以将数组转换为向量,然后将向量传递给MyFunction呢?是否有可以使用的单行转换,还是必须手动进行转换?

回答by AnT

In C++ language, multidimensional array declarations must always include all sizes except possibly the first one. So, what you are trying to do is not possible. You cannot declare a parameter of built-in multidimensional array type without explicitly specifying the sizes.

在 C++ 语言中,多维数组声明必须始终包括除第一个之外的所有大小。因此,您尝试做的事情是不可能的。您不能在不明确指定大小的情况下声明内置多维数组类型的参数。

If you need to pass a run-time sized multidimensional array to a function, you can forget about using built-in multidimensional array type. One possible workaround here is to use a "simulated" multidimensional array (1D array of pointers to other 1D arrays; or a plain 1D array that simulates multidimensional array through index recalculation).

如果需要将运行时大小的多维数组传递给函数,则可以忘记使用内置多维数组类型。这里一种可能的解决方法是使用“模拟”多维数组(指向其他一维数组的指针的一维数组;或通过索引重新计算模拟多维数组的普通一维数组)。

回答by M2tM

In C++ use std::vector to model arrays unless you have a specific reason for using an array.

在 C++ 中,除非您有使用数组的特定原因,否则使用 std::vector 对数组进行建模。

Example of a 3x2 vector filled with 0's called "myArray" being initialized:

一个被称为“myArray”的 0 填充的 3x2 向量被初始化的例子:

vector< vector<int> > myArray(3, vector<int>(2,0));

Passing this construct around is trivial, and you don't need to screw around with passing length (because it keeps track):

传递这个结构是微不足道的,你不需要纠结于传递长度(因为它会跟踪):

void myFunction(vector< vector<int> > &myArray) {
    for(size_t x = 0;x < myArray.length();++x){
        for(size_t y = 0;y < myArray[x].length();++y){
            cout << myArray[x][y] << " ";
        }
        cout << endl;
    }
}

Alternatively you can iterate over it with iterators:

或者,您可以使用迭代器对其进行迭代:

void myFunction(vector< vector<int> > &myArray) {
    for(vector< vector<int> >::iterator x = myArray.begin();x != myArray.end();++x){
        for(vector<int>::iterator y = x->begin();y != x->end();++y){
            cout << *y << " ";
        }
        cout << endl;
    }
}

In C++0x you can use the auto keyword to clean up the vector iterator solution:

在 C++0x 中,您可以使用 auto 关键字来清理向量迭代器解决方案:

void myFunction(vector< vector<int> > &myArray) {
    for(auto x = myArray.begin();x != myArray.end();++x){
        for(auto y = x->begin();y != x->end();++y){
            cout << *y << " ";
        }
        cout << endl;
    }
}

And in c++0x for_each becomes viable with lambdas

在 c++0x 中,for_each 可以通过 lambdas 实现

void myFunction(vector< vector<int> > &myArray) {
    for_each(myArray.begin(), myArray.end(), [](const vector<int> &x){
        for_each(x->begin(), x->end(), [](int value){
            cout << value << " ";
        });
        cout << endl;
    });
}

Or a range based for loop in c++0x:

或者在 c++0x 中基于范围的 for 循环:

void myFunction(vector< vector<int> > &myArray) {
    for(auto x : myArray){
        for(auto y : *x){
            cout << *y << " ";
        }
        cout << endl;
    }
}

*I am not near a compiler right now and have not tested these, please feel free to correct my examples.

*我现在不在编译器附近,也没有测试过这些,请随时纠正我的例子。



If you know the size of the array at compile time you can do the following (assuming the size is [x][10]):

如果您在编译时知道数组的大小,您可以执行以下操作(假设大小为 [x][10]):

MyFunction(int myArray[][10])

If you need to pass in a variable length array (dynamically allocated or possibly just a function which needs to take different sizes of arrays) then you need to deal with pointers.

如果您需要传入一个可变长度数组(动态分配或可能只是一个需要采用不同大小数组的函数),那么您需要处理pointers

And as the comments to this answer state:

正如对此答案的评论所述:

boost::multiarray may be appropriate since it more efficiently models a multidimensional array. A vector of vectors can have performance implications in critical path code, but in typical cases you will probably not notice an issue.

boost::multiarray 可能是合适的,因为它更有效地建模多维数组。向量的向量可能会对关键路径代码的性能产生影响,但在典型情况下,您可能不会注意到问题。

回答by EboMike

Pass it as a pointer, and take the dimension(s) as an argument.

将其作为指针传递,并将维度作为参数。

void foo(int *array, int width, int height) {
    // initialize xPos and yPos
    assert(xPos >= 0 && xPos < width);
    assert(yPos >= 0 && yPos < height);
    int value = array[yPos * width + xPos];
}

This is assuming you have a simple two-dimensional array, like int x[50][50].

这是假设您有一个简单的二维数组,例如int x[50][50].

回答by David Rodríguez - dribeas

There are already a set of answers with the most of the common suggestions: using std::vector, implementing a matrixclass, providing the size of the array in the function argument... I am only going to add yet another solution based on native arrays --note that if possible you should use a higher level abstraction.

已经有一组最常见建议的答案:使用std::vector,实现一个matrix类,在函数参数中提供数组的大小......我只会添加另一个基于本机数组的解决方案--注意如果可能,您应该使用更高级别的抽象。

At any rate:

好歹:

template <std::size_t rows, std::size_t cols>
void function( int (&array)[rows][cols] )
{
   // ...
}

This solution uses a referenceto the array (note the &and the set of parenthesis around array) instead of using the pass-by-value syntax. This forces the compiler not to decaythe array into a pointer. Then the two sizes (which could have been provided as compile time constantscan be defined as template arguments and the compiler will deduct the sizes for you.

此解决方案使用对数组的引用(注意&和 周围的括号集array),而不是使用按值传递语法。这会强制编译器不将数组衰减为指针。然后这两个大小(可以作为编译时常量提供)可以定义为模板参数,编译器将为您扣除大小。

NOTE: You mention in the question that the sizes are actually static constants you should be able to use them in the function signature ifyou provide the value in the class declaration:

注意:您在问题中提到大小实际上是静态常量,如果您在类声明中提供值,您应该能够在函数签名中使用它们:

struct test {
   static const int rows = 25;
   static const int cols = 80;
};
void function( int *array[80], int rows ) {
   // ...
}

Notice that in the signature I prefer to change the double dimension array for a pointer to an array. The reason is that thisis what the compiler interprets either way, and this way it is clear that there is no guarantee that the caller of the function will pass an array of exactly 25 lines (the compiler will notenforce it), and it is thus apparent the need for the second integer argument where the caller passes the number of rows.

请注意,在签名中,我更喜欢将二维数组更改为指向数组的指针。原因是是编译器以任何一种方式解释的,并且这种方式很明显不能保证函数的调用者将传递正好 25 行的数组(编译器不会强制执行它),并且它是因此显然需要调用者传递行数的第二个整数参数。

回答by Oliver Charlesworth

You can't pass an arbitrary size like that; the compiler doesn't know how to generate the pointer arithmetic. You could do something like:

你不能像那样传递任意大小;编译器不知道如何生成指针算法。你可以这样做:

MyFunction(int myArray[][N])

or you could do:

或者你可以这样做:

MyFunction(int *p, int M, int N)

but you'll have to take the address of the first element when you call it (i.e. MyFunction(&arr[0][0], M, N).

但是当你调用它时你必须获取第一个元素的地址(即MyFunction(&arr[0][0], M, N).

You can get round all of these problems in C++ by using a container class; std::vectorwould be a good place to start.

您可以通过使用容器类来解决 C++ 中的所有这些问题;std::vector将是一个很好的起点。

回答by André Caron

The compiler is complaining because it needs to know the size of the all but the first dimension to be able to address an element in the array. For instance, in the following code:

编译器抱怨是因为它需要知道除第一个维度之外的所有维度的大小,以便能够寻址数组中的元素。例如,在以下代码中:

int array[M][N];
// ...
array[i][j] = 0;

To address the element, the compiler generates something like the following:

为了寻址该元素,编译器生成如下内容:

*(array+(i*N+j)) = 0;

Therefore, you need to re-write your signature like this:

因此,您需要像这样重写您的签名:

MyFunction(int array[][N])

in which case you will be stuck with a fixed dimension, or go with a more general solution such as a (custom) dynamic 2D array class or a vector<vector<int> >.

在这种情况下,您将被固定维度卡住,或者使用更通用的解决方案,例如(自定义)动态 2D 数组类或vector<vector<int> >.

回答by JoshD

Yes: MyFunction(int **myArray);

是的: MyFunction(int **myArray);

Careful, though. You'd better know what you're doing. This will only accept an array of int pointers.

不过要小心。你最好知道你在做什么。这将只接受一个 int 指针数组。

Since you're trying to pass an array of arrays, you'll need a constant expression as one of the dimentions:

由于您正在尝试传递数组数组,因此您需要一个常量表达式作为维度之一:

MyFunction(int myArray[][COLS]);

MyFunction(int myArray[][COLS]);

You'll need to have COLSat compile time.

您需要COLS在编译时拥有。

I suggest using a vectorinstead.

我建议改用向量

回答by Steve Townsend

  1. Use a vector<vector<int> >(this would be cheating if underlying storage was not guaranteed to be contiguous).

  2. Use a pointer to element-of-array(int*) and a size(M*N) parameter. Here be dragons.

  1. 使用 a vector<vector<int> >(如果不能保证底层存储是连续的,这将是作弊)。

  2. 使用指向element-of-array( int*) 和size( M*N) 参数的指针。这里是龙。

回答by Arun

First, lets see why compiler is complaining.

首先,让我们看看为什么编译器会抱怨。

If an array is defined as int arr[ ROWS ][ COLS ];then any array notation arr[ i ][ j ]can be translated to pointer notation as

如果数组被定义为int arr[ ROWS ][ COLS ];那么任何数组表示法arr[ i ][ j ]都可以转换为指针表示法为

*( arr + i * COLS + j )

Observe that the expression requires only COLS, it does not require ROWS. So, the array definition can be written equivalently as

观察表达式 requires only COLS,它不需要ROWS。因此,数组定义可以等价地写为

int arr [][ COLS ];

But, missing the second dimension is not acceptable. For little more details, read here.

但是,缺少第二维是不可接受的。有关更多详细信息,请阅读此处

Now, on your question:

现在,关于你的问题:

Is there a way to rewrite the parameter list so that I can pass an array with any size to the function?

有没有办法重写参数列表,以便我可以将任意大小的数组传递给函数?

Yes, perhaps you can use a pointer, e.g. MyFunction( int * arr );. But, think about it, how would MyFunction()know where to stop accessing the array? To solve that you would need another parameter for the length of the array, e.g. MyFunction( int * arr, size_t arrSize );

是的,也许您可​​以使用指针,例如MyFunction( int * arr );. 但是,想想看,怎么MyFunction()知道在哪里停止访问数组?为了解决这个问题,你需要另一个数组长度的参数,例如MyFunction( int * arr, size_t arrSize );

回答by ajduff574

I don't know about C++, but the C99 standard introduced variable length arrays.

我不了解 C++,但 C99 标准引入了可变长度数组。

So this would work in a compiler that supports C99:

所以这可以在支持 C99 的编译器中工作:

void func(int rows, int cols, double[rows][cols] matrix) {
    for (int r = 0; r < rows; r++) {
        for (int c = 0; c < cols; c++) {
            printf("%f", matrix[r][c]);
        }
    }
}

Note that the size arguments come before the array. Really, only the number of columns has to be known at compile time, so this would be valid as well:

请注意,大小参数位于数组之前。实际上,在编译时只需要知道列数,所以这也是有效的:

void func(int rows, int cols, double[][cols] matrix)

For three or more dimensions, all but the first dimension must have known sizes. The answer ArunSaha linked to explains why.

对于三个或更多维度,除第一个维度外的所有维度都必须具有已知大小。ArunSaha 链接的答案解释了原因。

Honestly, I don't know whether C++ supports variable-length arrays, so this may or may not work. In either case, you may also consider encapsulating your array in some sort of matrix class.

老实说,我不知道 C++ 是否支持变长数组,所以这可能有效,也可能无效。在任何一种情况下,您还可以考虑将数组封装在某种矩阵类中。

EDIT:From your edit, it looks like C++ may not support this feature. A matrix class is probably the way to go. (Or std::vector if you don't mind that the memory may not be allocated contiguously.)

编辑:从您的编辑看来,C++ 可能不支持此功能。矩阵类可能是要走的路。(或者 std::vector 如果您不介意内存可能不会连续分配。)