在C++中从函数返回一个二维数组

3

我想使用从函数返回的二维整数数组,应该如何定义函数返回值? 我用了int **,但编译器报错:

int**  tableCreator(){
    int** table=new int[10][10];
    for(int xxx=1;xxx<10;xxx++){
        for(int yyy=1;yyy<10;yyy++){
            table[xxx][yyy]=xxx*yyy;
        }
    }
    return(table);  //Here:cannot convert from 'int (*)[10]' to 'int **'
}
4个回答

6

试试这个:

#include <cstdio>
#include <cstdlib>


int** createTable(int rows, int columns){
    int** table = new int*[rows];
    for(int i = 0; i < rows; i++) {
        table[i] = new int[columns]; 
        for(int j = 0; j < columns; j++){ table[i][j] = (i+j); }// sample set value;    
    }
    return table;
}
void freeTable(int** table, int rows){
    if(table){
        for(int i = 0; i < rows; i++){ if(table[i]){ delete[] table[i]; } }
        delete[] table;    
    }
}
void printTable(int** table, int rows, int columns){
    for(int i = 0; i < rows; i++){
        for(int j = 0; j < columns; j++){
            printf("(%d,%d) -> %d\n", i, j, table[i][j]);
        }    
    }
}
int main(int argc, char** argv){
    int** table = createTable(10, 10);
    printTable(table, 10, 10);
    freeTable(table, 10);
    return 0;
}

你需要第二个循环来在C语言中分配一个二维数组,同样的操作用于释放它。一个二维数组实质上是一个数组的数组,因此可以表示为指针数组。该循环初始化了指向指针的数组。
根据与@Eric Postpischil的对话澄清:更改createTable以接受行/列计数以进行真正的动态分配。

语句“在C语言中,分配二维数组需要两个循环以及类似的释放操作”是错误的。除最外层维度以外的所有维度固定大小的多维数组可以通过单个new进行容易分配,并且可以通过单个delete进行回收,使用多个newdelete调用是浪费的。可变长度数组可以通过各种方式支持,而不需要多次分配和释放。 - Eric Postpischil
但这仅在您分配固定长度的行时才需要。例如 X[10][10]。如果您的行具有可变长度,即真正的数组数组,则确实需要循环。 - mohaps
请看一下已接受的答案 :) 它确实执行了循环。如果您正在动态分配例如allocate2DArray(int i, int j),那么您必须进行循环,不是吗? - mohaps
“可变长度数组”指的是形如int a[M]int a[M][N]等的数组,其中一个或多个维度不是编译时常量。具有不同长度的数组数组不能被正确地称为“多维数组”,它是一种不同的数据结构。问题并没有要求这样的数据结构。它甚至没有要求我所描述的可变长度数组;它只是请求一个具有常量维度的简单二维数组。 - Eric Postpischil
同意,Eric。那正是我想要的。感谢澄清。我已在我留下的下一个评论中进行了澄清。循环需要用于动态分配。个人而言,我更喜欢1-D数组并通过y*W+x访问。更容易管理。 - mohaps

5
int** table=new int[10][10];

这是错误的。在C/C ++中,您不能以这种方式分配2D动态数组的空间。

同时,您声明了数组大小为10,因此索引范围为0-9,但您正在尝试在嵌套的for循环中为索引10赋值,这也是不正确的。

您可以使用以下代码进行分配:

int** table = new int*[10];
for (int i = 0; i < 10; ++i)
{
   table[i] = new int[10];
}

2
如果在编译时已知维度,则可以按以下方式为二维数组分配空间。也就是说,分配 new int[10][10] 是正确的。需要改变 table 的声明。如果数组是矩形的(没有不同长度的行),那么分配多个指针并使用指向指针的指针是浪费的。仍然可以在单个调用中执行分配,并且可以通过辅助类或其他构造支持多个维度。 - Eric Postpischil
此外,创建指向指针的指针会在使用表时导致多次指针查找,并且会干扰编译器对代码进行优化。当存在指向指针的指针时,编译器很难确定它们实际上指向不同的东西,因此不能彼此别名。当将表作为指向单个对象的指针传递时,编译器知道对不同索引的引用是内存中的不同位置。这允许对代码进行重新排列,从而可能提高执行时间。 - Eric Postpischil

3

通常,用于指向数组的类型是指向数组元素的指针。由于一个二维int数组是一个int数组的数组,因此您需要一个指向int数组的指针。这种类型的C++语法为int (*)[N],其中N是某个维度。以下代码演示了这一点:

#define N   10

int (*tableCreator())[N]
{
    int (*table)[N] = new int[N][N];

    for (int i = 0; i < N; ++i)
        for (int j = 0; j < N; ++j)
            table[i][j] = i*j;

    return table;
}


#include <iostream>


int main()
{
    int (*t)[N] = tableCreator();

    for (int i = 0; i < N; ++i)
    {
        for (int j = 0; j < N; ++j)
            std::cout << t[i][j] << ' ';
        std::cout << '\n';
    }

    delete [] t;

    return 0;
}

0

I. 数组不是指针。

II. 为什么不用vector<vector<int> >

III. 如果不用,那么:

typedef int Int10Array[10];
Int10Array *arr = new Int10Array[10];

IV. 为什么要超出边界写代码?你想要显式的鼻部恶魔吗?

for(int xxx = 0; xxx < 10; xxx++)
             ^^^      ^^^^

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