【问题标题】:Trying to understand initialization of array C++试图理解数组 C++ 的初始化
【发布时间】:2021-12-28 14:45:50
【问题描述】:

我正在使用 C++ 构建一个数组,然后将其传递给 Python(类似于:Embed python / numpy in C++)。我是 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]) 不同。我认为这是你困惑的根源。
  • 啊,这样就更有意义了。那么,指针周围的括号意味着指针指向对象吗?像这样……?
  • 这是变量的声明语法。在复杂的情况下,它是出了名的棘手,因为我们在名称 (p) 之前写了一些东西,在之后写了一些东西,而且顺序并不容易理解。在某些情况下需要括号来强制需要的类型,就像我上面做的例子一样。 int (*p)[5] 表示 p 是指向 5 个整数数组的指针。 int *p[5] 被解析为 int *(p[5]),这是一个由 5 个指向 int 的指针组成的数组。

标签: c++ arrays pointers


【解决方案1】:
double(*c_arr)[SIZE]{ new double[SIZE][SIZE] };

以上是/可以读作:

c_arr 是一个指向大小为SIZE 的数组的指针。接下来,new double[SIZE][SIZE] 创建一个二维数组,并返回一个指向其第一个元素的指针(也是一个双精度数组)。接下来,用new double[SIZE][SIZE]的最后一步返回的指针初始化指针c_arr

现在让我们来看看:

double *c_arr[numberRows][numberColumns];

在这种情况下,c_arr 是一个指向 double 的二维指针数组。所以你不能用一个指针初始化这个二维指针数组,比如:

 double d=15; 
 double *c_arr[5][6]=&d ;//incorrect

现在来看看你的错误

当我构造这样一个函数时,第二次出现columns变量时出现错误:表达式必须有一个常量值——参数“columns”的值不能用作常量

这是因为,在 C++ 中,数组的大小必须是编译时间常数(constant expression)。比如,

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 要通过load_data 函数返回指针,您可以使用我在答案末尾添加的方法。看看这个。现在函数load_data 返回一个指向double 大小为5 的数组的指针。再次注意,我已经给出了特定数字(例如 4 和 5)的示例。如果您有一些常量表达式,那么您可以使用它们而不是数字 4 和 5。您应该使用动态大小的容器,例如 std::vector
  • 您似乎没有使用函数参数rowscolumns。如何使用函数参数来构造数组指针?这不可能吗?
  • @CopyOfA 使用参数rowscolumns不可能,因为它们都不是常量表达式。另一方面,如果您使用std::vector,则可以完全避免这些问题。
  • @CopyOfA 基本上是的如果你使用数组。另一方面,如果您使用std::vector,那么您可以使用传递的参数,例如rowscolumns
【解决方案2】:

这种初始化数组的方法是什么?

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 这不是你做的。动态数组的大小为numberRows。你可以初始化一个指针数组。
  • 我有点困惑。我认为数组的大小是numberColumns,因为这是第一次调用(double(*c_arr)[numberColumns])。
  • @CopyOfA 动态数组的大小为numberRows。动态数组的元素是大小为numberColumns 的数组。 c_arr 指向第一个元素。
猜你喜欢
  • 2020-10-03
  • 2017-03-08
  • 2013-05-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-02
  • 2017-07-21
  • 1970-01-01
相关资源
最近更新 更多