无法将double [] []转换为double **

时间:2014-02-12 15:02:06

标签: c++ double

我有一个需要3个参数的函数,第一个是** double。

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

当我从main调用它时,我正在尝试使用normalizeDataZeroMeanUnitSD(data,68​​1,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();

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

8 个答案:

答案 0 :(得分:6)

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

以这种方式思考:double**意味着指向许多指针的指针。但是double[][]没有任何指针。充其量,任何维度的数组仍然只有一个指针:到其连续存储的开头。

答案 1 :(得分:4)

您可以使用模板:

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] = ...;
      }
   }
}

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

答案 2 :(得分:3)

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

答案 3 :(得分:3)

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

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

答案 4 :(得分:3)

以下是如何使其发挥作用的建设性答案。

基本上,您需要生成一个数组,该数组具有指向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

答案 5 :(得分:3)

是的,我再次对此咆哮。

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

锯齿状数组是(double** bar;)。这是一堆不同的数组:首先,你分配一个指针数组,长度为268个成员。每个指针都指向一个双精度数组,长24个元素。 Bar只是一个指针,所以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++!

答案 6 :(得分:2)

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

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

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

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

对于行主要和列主要定义,请查看this

对于您编辑的问题,是的,您可以使用**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数组。

答案 7 :(得分:2)

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>>,您不再需要担心内存管理,也不必将正确的维度传递给函数。