我有一个需要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();
有没有办法使用**数据做同样的事情?
答案 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>>
,您不再需要担心内存管理,也不必将正确的维度传递给函数。