2017-02-22 6 views
7

パラメータとしてポインタのポインタをとるCライブラリAPI関数があるとします。しかし、私はC++でプログラミングしているので、動的メモリを扱うためにstd vectorを利用したいと思います。どのようにベクトルのベクトルをポインタのポインタに効率的に変換できますか?今私はこれを使用しています。ベクトルのベクトルをポインタのポインタに変換する

#include <vector> 

/* C like api */ 
void foo(short **psPtr, const int x, const int y);  

int main() 
{ 
    const int x = 2, y = 3; 
    std::vector<std::vector<short>> vvsVec(x, std::vector<short>(y, 0)); 
    short **psPtr = new short*[x]; 

    /* point psPtr to the vector */ 
    int c = 0; 
    for (auto &vsVec : vvsVec) 
     psPtr[c++] = &vsVec[0]; 

    /* api call */ 
    foo(psPtr, x, y);   

    delete[] psPtr; 
    return 0; 
} 

これは目標を達成するための最良の方法ですか?この場合、イテレータまたはいくつかのstdメソッドを使って "新しい削除"を取り除くことはできますか?前もって感謝します。

編集: 私は現在、このバージョンを使用してCコードとインターフェイスしています。私はここにそれを掲示しています。

#include <vector> 

/* C like api */ 
void foo(short **psPtr, const int x, const int y);  

int main() 
{ 
    const int x = 2, y = 3; 
    std::vector<std::vector<short>> vvsVec(x, std::vector<short>(y, 0)); 
    std::vector<short*> vpsPtr(x, nullptr); 

    /* point vpsPtr to the vector */ 
    int c = 0; 
    for (auto &vsVec : vvsVec) 
     vpsPtr[c++] = vsVec.data(); 

    /* api call */ 
    foo(vpsPtr.data(), x, y);   

    return 0; 
} 

もっと見るC++ like私に。全てに感謝!

+3

ドロップベクターの1つのレベルとその平坦ベクトルの最初の要素へのポインタのアドレスを取ります。 – rubenvb

+0

psPtrをベクトルに置き換えて、アルゴリズムの一部の機能で設定することができます。 – BlueWanderer

+0

API関数は、sizeパラメータを必要とするか、またはヌルポインタが最後の要素を表すという規約を持っています。その場合、最後に 'nullptr'を追加する必要があります。 –

答えて

4

これは目標を達成するための最良の方法ですか?

ベクトルのベクトルがpsPtrよりも長く存続することが確かな場合は、はいです。そうしないと、psPtrに無効なポインタが含まれる危険性があります。

この場合、イテレータまたはいくつかのstdメソッドを使用して「新しい削除」を取り除くことはできますか?

はい。

std::vector<short*> psPtr(vvsVec.size()); 

、その後、C API関数の呼び出しで&psPtr[0]を使用する:私が使用して示唆しています。これにより、コードからメモリ管理の負担が軽減されます。

foo(&psPtr[0]);   
+0

これはかなりきれいに見えます。以前はポインタのベクトルを考えなかった。ありがとう! – yc2986

+0

@ yc2986、よろしくお願いします。 –

+0

@ yc2986:ポインタのベクトルは、通常、アンチパターンです。あなたがこれをやろうと決して考えなかったなら、これは実際には良いことです。 – IInspectable

3
std::vector<short*> vecOfPtrs; 
for (auto&& vec : vvsVec) 
    vecOfPtrs.push_back(&vec[0]); 

foo(&vecOfPtrs[0]); 
+0

事前にコンテナ 'vecOfPtrs'のサイズを知っているので、実際にそのサイズに初期化する必要があります。これにより、潜在的なメモリの再配置やサイズ変更による潜在的な例外が防止されます。 – IInspectable

+0

なぜ '&vec [0]'で、 'vec.data() 'でないのですか?私は 'vecを使用する少なくとも3つの理由を考えることができます。'&vec [0]'の上にdata() 'を、' vec.data() 'の上に'&vec [0] 'を使用する場合はゼロを返します。 (空ベクトル、 'ベクトル'、 'std :: addressof'問題は重要度が低くなる) – Yakk

+0

@Yakk私は古い習慣がC++ 03から難しいと思う。 'vec.data()'が優れています。しかし、vec.data()は空ベクトルの場合でも 'vec [0]'を返す必要があり、C++標準ではone-past-the-endのアドレスを取ることができるため、最初の理由はまったく良くありませんアレイの – rlbond

関連する問題