无法将双精度 [] [] 转换为双精度 **

Cannot convert double [] [] to double **

本文关键字:双精度 转换      更新时间:2023-10-16

我有一个函数,它接受 3 个参数,第一个是 **double。

 normalizeDataZeroMeanUnitSD(double ** trainingActions, int numberOfTrainingActions, int descriptorDimension)

当我从main调用它时,我正在尝试使用normalizeDataZeroMeanUnitSD(data,681,24);但是,我正在接收

cannot convert parameter 1 from 'double [681][24]' to 'double **'

这就是我构造数据数组的方式:

fstream infile;
infile.open("gabor\Data.txt");
double data[681][24];
while (!infile.eof()) 
     {
        for(int j=0;j<681;j++) 
        {
            for(int k=0; k<24;k++) 
            {
                infile >> data[j][k];
           }
        }
 } 
 infile.close();

有没有办法使用**数据做同样的事情?

错误非常明显:数据类型double [681][24]double **不同。虽然double[681]确实可以衰减到指向其第一个元素的指针(因此,double*),但这并不意味着double[681][24]可以衰减到double**

可以这样想:double**意味着指向许多指针的指针。但是double[][]没有任何指针。充其量,一个 ANY 维度的数组仍然最多只有一个指针:指向其连续存储的开头。

您可以使用模板:

template<std::size_t M, std::size_t N>
void normalizeDataZeroMeanUnitSD(double (&trainingActions)[M][N], int descriptorDimension)
{
   for( std::size_t m = 0; m < M; ++m )
   {
      for( std::size_t n = 0; n < N; ++n )
      {
          trainingActions[m][n] = ...;
      }
   }
}

但是,如果您使用许多不同大小的数组调用它,请注意代码膨胀。

使用以下任何声明。两者是等效的。

NormalizeDataZeroMeanUnitSD(double trainingActions[][24], int numberOfTrainingActions, int descriptorDimension)
NormalizeDataZeroMeanUnitSD(double trainingActions[681][24], int numberOfTrainingActions, int descriptorDimension)

当您声明 2D 数组时,它会占用连续的内存位置。因此,您至少需要指定列数(在行主要体系结构的情况下)。

有关行主定义和列主定义,请查看此内容。

对于您编辑的问题,是的,您可以使用 **data 进行声明。动态分配data数组。但请记住在完成它后释放它。

double **data=new double*[681];
for (int i=0;i<681;i++)
{
  data[i]=new double[24];
}
//do what you want to do

for (int i=0;i<681;i++)
{
  delete [] data[i];
}
delete [] data;

现在,您的函数原型可以像void func(double **pp)一样data因为它是一个指针而不是一个 2D 数组。

2D 阵列是一个连续的存储区域。该函数需要一个指向指针的指针。这些是不兼容的。

该函数需要一个指向数组的指针数组;你有一个数组数组。一些选项是:

  • 将函数更改为更友好的类型,也许double*指向连续二维数组的第一个元素;或者
  • 构建一个单独的指针数组,指向二维数组的每一行;或
  • 将数据重构为指向数组的指针数组。

这是如何使其工作的建设性答案。

基本上,您需要生成一个数组,该数组具有指向 2D 数组的每个 1D 切片的指针。

double data[N][M] = {...};
double *dataPtrs[N];
for(size_t n=0; n<N; ++n) {
  dataPtrs[n] = data[n];
}
normalizeDataZeroMeanUnitSD(dataPtrs, N, M); // order of N and M might be wrong

是的,我又要咆哮了。

在C++中,尽管具有相似的语法,但二维数组不是交错数组。 二维数组(double foo[681][24])在内存中连续分配。当你尊重一个2D数组(foo[j][i])时,它实际上是*(foo+24*i+j)。这一切都是在引擎盖下完成的。sizeof(foo)==sizeof(double)*681*24 .

交错数组是 (double** bar; )。这是一堆不同的数组:首先,分配一个指针数组,长度为 268 个成员。每个指针将指向一个双精度数组,长度为 24 个元素。酒吧只是一个指针,所以sizeof(bar)==sizeof(void*).

更烦人的是,2D 数组(或任何维度的静态数组)的行为与C++中的所有其他类型的相反,在以下保护中:它们通过引用隐式传递,导致下面的奇怪现象。

void foo(double bar[24][24]) { std::cout << sizeof(bar) << std::endl;}
int main() {
  double test[24][24];
  std::cout << sizeof(test) << std::endl;//returns sizeof(double)*24*24
  foo(test);//returns sizeof(void*), implicitly passed by reference, opossite of the rest of c++!

double[][]double**不是一回事。

double**是指向指针的指针。 double[][] 是分配为连续存储的二维数组。

为了将"二维数组"传递给函数,您需要创建一个指向数组的指针数组。例如:

double* array_2d[681];
for(unsigned int i=0; i<681; ++i) {
    array_2d[i] = new double[24];
}
normalizeDataZeroMeanUnitSD(array_2d, 681, 24);

记得稍后删除 array_2d 的每个元素 !

更好的是,更改normalizeDataZeroMeanUnitSD以引用std::vector<std::vector<double>>,您不再需要担心内存管理,也不必将正确的维度传递给函数。