尝试理解C++数组初始化

3

我正在使用C++构建一个数组,然后将其传递到Python(类似于:在C++中嵌入Python / Numpy)。我对C++不太熟悉, 对代码的一些细节感到困惑。我希望能够理解这段代码的工作原理,因为我需要对其进行更改。所以我的问题是:这种初始化数组的方法是什么?

const int SIZE{ 10 };
double(*c_arr)[SIZE]{ new double[SIZE][SIZE] };

记录一下,我通过调用以下代码使其成为一个矩形数组:

const int numberRows = 5000;
const int numberColumns = 500;
double(*c_arr)[numberColumns]{ new double[numberRows][numberColumns] };

我填充数组:

// fill the array from a file
std::string line;
int row = 0;
int column = 0;
while (std::getline(dataFile, line)) {
    std::stringstream lineStream(line);
    std::string cell;
    while (std::getline(lineStream, cell, '\t')) {
        c_arr[row][column] = std::stod(cell);
        column++;
    }
    row++;
    column = 0;
    if (row == numberRows) {
        break;
    }
}

我仍然不理解 double(*c_arr) 是什么意思。每当我尝试用不同的方式来初始化这个数组时,都会出现错误。例如:double *c_arr[numberRows][numberColumns]; 当我尝试填充数组 c_arr[row][column] = std::stod(cell); 时,就会出现错误。如果我将初始化更改为:double c_arr[numberRows][numberColumns]; ,那么在运行时就会出现分段错误。我最终想要实现一个返回指向数组的指针的函数;像这样:

double *load_data(int rows, int columns) {
    double(*c_arr)[columns]{ new double[rows][columns] };
    //fill array here
    return (c_arr)
}

当我构造这样一个函数时,在第二次出现columns变量时出现错误:expression must have a constant value -- the value of parameter "columns" cannot be used as a constant。我不太清楚如何解决这个问题,但我希望如果我能理解数组初始化,我就能正确地构造load_data函数。

指向数组的指针(int (*p)[5])与指针数组(int *p[5])是不同的。我认为这是你困惑的根源。 - chi
啊,那样就有点意思了。所以,括号围绕指针意味着指针指向对象?类似这样...? - CopyOfA
这是变量的声明语法。在复杂情况下,它非常棘手,因为我们在名称(p)之前写了一些东西,在名称之后写了一些东西,而且顺序并不容易理解。有些情况下需要使用括号来强制所需的类型,就像我上面做的示例一样。int (*p)[5] 表示 p 是一个指向 5 个整数数组的指针。而 int *p[5] 则被解析为 int *(p[5]),表示一个包含 5 个指向整数的指针的数组。 - chi
2个回答

2
double(*c_arr)[SIZE]{ new double[SIZE][SIZE] };

上述内容可以理解为:
c_arr是一个大小为SIZE的数组的指针。接下来,new double[SIZE][SIZE]创建了一个二维数组,并返回其第一个元素(也是一个double类型的数组)的指针。然后,指针c_arr被初始化为上一步从new double[SIZE][SIZE]返回的指针。
现在让我们看看:
double *c_arr[numberRows][numberColumns];

在这种情况下,c_arr 是一个指向双精度浮点数的二维指针数组。因此,您不能使用单个指针初始化这个二维指针数组,例如:
 double d=15; 
 double *c_arr[5][6]=&d ;//incorrect

接下来要谈及您的错误

当我构建这样一个函数时,第二次出现columns变量时会出现一个错误:表达式必须是一个常量值——参数"columns"的值不能被用作常量。

这是因为,在C++中,数组的大小必须是一个编译时常量(常量表达式)。例如,

int n = 10;
double arr[n]; //incorrect

正确的方式应该是:
const int n = 10;
double arr[n];//correct

因此,在您的代码中,名为columns的变量不是常量表达式,这就是您出现上述错误的原因。

要正确返回数组指针,您可以修改load_data函数以如下方式:

auto load_data(int rows, int columns) -> double (*)[5]{

    double(*c_arr)[5]{ new double[4][5] };
    
    //fill array here
    return c_arr;
}

在上述修改的load_data中,您可以使用其他常量表达式,而不是使用数字4和5。

谢谢您的回复。根据错误信息,我该如何将这样的参数传递给数组构造函数呢?应该是 double *load_data(int rows, const int columns) {...} 吗?此外,如果我将 c_arr 初始化为 double(*c_arr)[numberCols]{ new double[numberRows][numberCols] };,则会出现返回类型错误。我以为我正在返回一个指针,所以这应该可以工作,对吗? - CopyOfA
看起来你没有使用函数参数 rowscolumns。我该如何使用函数参数来构造数组指针?这不可能吗? - CopyOfA
嗯...所以,数组大小必须硬编码吗? - CopyOfA
1
基本上是的,如果你使用数组。另一方面,如果你使用std::vector,那么你可以像rowscolumns这样使用传递的参数。 - Jason
让我们在聊天中继续这个讨论 - CopyOfA
显示剩余2条评论

2

what is this method of initializing an array?

const int SIZE{ 10 };
double(*c_arr)[SIZE]{ new double[SIZE][SIZE] };

c_arr是一个指向double[SIZE]的指针,即指向双精度浮点数数组的指针。

new double[SIZE][SIZE]分配了一个默认初始化的double[SIZE]的动态数组。结果是第一个元素的指针。该指针用于初始化c_arr


谢谢!更多问题:当我初始化一个矩形数组时,我会初始化double(*c_arr)[numberColumns]{ new double[numberRows][numberColumns] }。为什么我要声明numberColumns是动态数组的大小?另外,为什么我不能将数组指针初始化为double *c_arr[numberRows][numberColumns] - CopyOfA
@CopyOfA 这不是你所做的。动态数组的大小是 numberRows。您可以初始化指针数组。 - eerorika
我有点困惑。我以为数组的大小是numberColumns,因为这是第一个调用(double(*c_arr)[numberColumns])。 - CopyOfA
@CopyOfA 动态数组的大小为 numberRows。动态数组的元素是大小为 numberColumns 的数组。c_arr 指向第一个元素。 - eerorika

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