0

有一个函数,接受二维数组:

void foo ( double ** p ) 
{ /*writing some data into p*/ }

我不想将原始二维数组传递给这个函数,因为我不想管理内存调用newdelete. 另外我不想将函数签名更改为void foo ( std::vector< std::vector<double> >& ). 而且我不能foo作为模板函数(在我的项目中它是一个 COM 接口方法)。

我想传递一些 RAII 对象来装饰它,比如

void foo ( double * p ){}
std::vectore<double> v(10);
p( &v[0] );

有没有办法为二维数组做到这一点?我试过

std::vector< std::vector<int> > v;
foo( &v[0][0] )

std::vector< std::tr1::shared_ptr<int> > v;

但我得到编译错误error C2664 - cannot convert parameter

另外,在这种情况下,可以确定函数内部的原始地址算术可以正常工作吗?

没有 C++11,二维数组的大小是已知的。

4

2 回答 2

1

一种可能的解决方案是更改:

std::vector< std::vector<int> > v;
foo( &v[0][0] )

std::vector< std::vector<int> > v;
std::vector<int*> v_ptr;
for (...) {
    v_ptr[i] = &v[i][0];
}
foo( &v_ptr[0])
于 2012-08-17T12:23:38.757 回答
1

尽管 Andreas 已经回答了您的问题,解决了您的特定问题,但我想指出,尽管这有效,但可能不是您想要做的。

当您使用 C++(而不是更容易使用的语言)时,我假设您关心性能。在这种情况下,您的方法很可能从一开始就是错误的,因为它double**表示数组数组(或者更确切地说可以表示)而不是 2D 数组。为什么这很糟糕?因为,就像std::vector< std::vector<int> >示例一样,需要多次分配,并且生成的内存是不连续的(这对缓存不利),这与double array[N][M].

对于 2D 数组,您实际上应该使用具有索引计算的 1D 数组,这对缓存更加友好。这当然不允许[x][y]- 样式索引(相反,您必须使用[x+N*y]or [y+M*x],这取决于您选择“Fortran 顺序”或“C 顺序”),但可以避免缓存问题,并且只需要一次分配(和一个简单的double*指针)。

如果您要迭代数组的所有元素,如

for(unsigned x = 0; x < N; ++x) for(unsigned y = 0; y < M; ++y)
{
    unsigned idx = y + M * x;
    p[idx] = bar(x, y); // equivalent to p[x][y] = bar(x,y) in the array-of-arrays case
}

您甚至可以避免乘法,因为这基本上只是一个 1D 迭代,并额外生成了 2D 索引

for(unsigned x = 0, idx = 0; x < N; ++x) for(unsigned y = 0; y < M; ++y, ++idx)
{
    p[idx] = bar(x, y);
}
于 2013-08-17T09:36:36.137 回答