将 RAII 结构作为 2D 数组传递到函数中

to pass RAII structure as 2D-array into a function

本文关键字:函数 数组 2D RAII 结构      更新时间:2023-10-16

有一个函数,接受2D数组:

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

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

我想传递一些 RAII 对象对其进行原始装饰,例如

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

有没有办法为 2D 阵列做到这一点?我试过了

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,2D阵列的大小是已知的。

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

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])

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

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

对于 2D 数组,您实际上应该使用带有索引计算的一维数组,这更加有利于缓存。这当然不允许[x][y]式索引(相反,您必须使用[x+N*y][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);
}