0

2D配列を受け入れる関数があります:

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

newメモリ呼び出しを管理したくないので、生の 2D 配列をこの関数に渡したくありませんdelete。また、関数の署名を に変更したくありません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 配列のサイズはわかっています。

4

2 に答える 2

1

考えられる解決策の 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

アンドレアスはあなたの特定の問題を解決するあなたの質問にすでに答えていますが、それは機能しますが、おそらくあなたがやりたいことではないことを指摘したいと思います。

C++ を使用している (そして使いやすい言語ではない) ため、パフォーマンスに関心があると思います。その場合、2D 配列ではdouble**なく、配列の配列を表す (またはを表すことができる)ため、最初からアプローチが間違っている可能性があります。なぜこれが悪いのですか?例と同じようにstd::vector< std::vector<int> >、複数の割り当てが必要であり、結果のメモリはdouble array[N][M].

2D 配列の場合、実際にはインデックス計算で 1D 配列を使用する必要があります。これは、はるかにキャッシュに適しています。[x][y]もちろん、これはスタイルのインデックス付けを許可しません(代わりに、「Fortran オーダー」または「C オーダー」の選択に応じて[x+N*y]orを使用する必要があります) が、キャッシュの問題を回避し、単一の割り当て (および単純なポインター) のみを必要とします。[y+M*x]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
}

これは基本的に2Dインデックスの追加生成を伴う1D反復であるため、乗算を回避することもできます

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 に答える