2009-11-13 3 views
5

std :: vector(T *データなどが指す)に含まれるデータの所有権を別の構造に移し、ベクトルが範囲外になった後にぶら下がっているポインタになりますか?ベクトルが有効範囲外になったときにデータが解放されないようにする

編集:私はデータをコピーしたくありません(これは簡単ですが効果的ではありません)。これをエミュレートするために私の心に来るだけの事はある

template<typename T> 
    T* transfer_ownership(vector<T>&v){ 
    T*data=&v[0]; 
    v.clear(); 
    ...//<--I'd like to make v's capacity 0 without freeing data 
} 

int main(){ 
    T*data=NULL; 
    { 
     vector<double>v; 
     ...//grow v dynamically 
     data=transfer_ownership<double>(v); 
    } 
    ...//do something useful with data (user responsible for freeing it later) 
    // for example mxSetData(mxArray*A,double*data) from matlab's C interface 
} 

{ 
    vector<double>*v=new vector<double>(); 
    //grow *v... 
    data=(*v)[0]; 
} 

し、データが後でどちらか解放されます

具体的には、私のような何かをしたいのですがまたは(私の場合は)mxSetData(mxArray A、doubleデータ)として使用されます。しかし、これは小さなメモリリーク(vの容量、サイズなどを処理するためのデータ構造体ですが、もちろんデータそのものではありません)をもたらします。

漏れなく可能ですか?

+0

これはかなり混乱しています。また、C++フォーラムで質問してみてください。 – Nzbuu

+0

mxSetDataとmxArrayは、(C mexファイルを使用して)matlab Cインタフェースの一部です。 – spirov

+0

はい、本当にMatlab *の質問ではありません。* C++を知らない限り、Matlabがあなたを助けるためにここに来ていることを知っている人は何も寄付することができません。 – quark

答えて

0

このような機能はありますか?

int main() 
{ 
    double *data = 0; 
    { 
     vector<double> foo; 
     // insert some elements to foo 

     data = new double[foo.size()]; 
     std::copy(foo.begin(), foo.end(), &data[0]); 
    } 

    // Pass data to Matlab function. 
    delete [] data; 
    return 0; 
} 
5

簡単な回避策は、あなたが所有するものとベクトルを交換することになります。

vector<double> myown; 

vector<double> someoneelses = foo(); 

std::swap(myown, someoneelses); 

厳しい多分、より良いアプローチは、ベクターのための独自のアロケータを書き、そしてそれは、プールの外に割り当てさせていますあなたは維持します。個人的な経験はありませんが、それほど複雑ではありません。

+0

シンプルでクリーンで、パフォーマンスの視点から非常に効果的です。誰かが範囲外になった後に生きるために、ヒープや他の場所にmyownを作成することができます。 –

+1

、あるいはさらに短く: 'foo()。swap(myown);' – sellibitze

+0

カスタムアロケータを指摘してくれてありがとう。アロケータをallocator_derived に継承しました(ユーザによってフラグが設定されている場合、つまりベクターを解放する直前に削除しないよう注意してください)。これはうまくいくし、いくつかのシステムではいくつかの注意を払って漏れません...しかし、残念ながらすべてではありません。例えば、これはmac(gcc 4.2.1)では動作しますが、64bit Linux(gcc 4.3)ではベクトル>は派生した動作を使用していないようです。なぜ私は分からない。 – spirov

1

ベクトルに値が含まれている場合は、コピーすることができます(std :: copy、std :: swapなどを呼び出すと発生します)。プリミティブでないオブジェクトをベクター内に保持し、それらをコピーしたくない場合(別のデータ構造で使用する場合)、ポインタの格納を検討してください。

5

std :: vectorを使用する点は気にする必要はありませんその中のデータ:

  • あなたのアプリケーションに沿ってあなたのすべてのベクトルを保つ;
  • const-refで他の関数に渡します(不要なコピーを避けるため)。
  • フィード機能は、ポインタへのポインタが&v[0]であると予想します。

あなたが本当にあなたのベクトルを維持したくない場合は、あなたのデータをコピーする必要があります - std::vectorは外のスコープに行くとき、それはその内容を破壊する保証ので、あなたは、所有権を譲渡することはできません。その場合はstd::copy()アルゴリズムを使用してください。

+1

+1は、Cのようなインタフェースとの互換性のための '&v [0]'構造に言及しています。 –

+0

3番目の項目はキーです。なぜなら、コピーせずにベクトルの内容を外部関数に渡すのは、OPが望むものの大部分です。 – quark

-2

コンテナ間でデータをコピーするのではなく、コンテナ間でデータの所有権を転送したいので、次のようにスマートポインタのコンテナを使用することをお勧めします。

void f() 
{ 
    std::vector<boost::shared_ptr<double> > doubles; 
    InitVector(doubles); 

    std::vector<boost::shared_ptr<double> > newDoubles(doubles); 
} 

標準コンテナは、常に彼らはカプセル化したデータをコピーするので、あなたは本当に、それのコピーを作成することなく、標準コンテナの間でのデータの所有権を譲渡することはできません。高価なオブジェクトをコピーするオーバーヘッドを最小限に抑えたい場合は、参照カウントのスマートポインタを使用して高価なデータ構造をラップすることをお勧めします。boost::shared_ptrは、このコピーを作成するのがかなり安いので、このタスクに適しています。

関連する問題