2011-01-25 8 views
2

ベクトルの要素へのポインタのベクトルを作成する簡単な方法はありますか?私はあなたがこれを行う必要がありますない理由を見ない参照C++のベクトルからポインタのベクトルを取得

+3

何をお探しですか?どのような場合でも、あなたが今持っているものは悪いです:関数ローカル変数 'v'の要素へのポインタを取得しています。それらのポインタはあなたが戻ってくるとすぐにぶら下がります。パラメータを参照にする必要があります。 – GManNickG

+2

与えられた例は、関数が終了した後に存在しないオブジェクトへのポインタのベクトルになります。プロトタイプを 'std :: vector fn(std :: vector &v) 'にしたい、つまり破壊されるコピーではなくソースベクトルの参照を渡すとします。 – pmdj

+0

そのコードは、ぶら下がっているポインタを作成し、 'v'とその要素のすべてが' fn'が残ったときに割り当て解除されるので、ほとんどのシステムでは簡単にクラッシュしたり予期せず動作します。 – Philipp

答えて

1

@Benoitが示唆しているように、これらのポインタを格納するのは悪い考えです。あなたが本当にがそれをやりたいなら、あなたはこのようなstd::transformを使用することができます。すべての

template<class T> 
struct Address 
{ 
    T* operator()(T& t) const 
    { 
     return &t; 
    } 
}; 


template<class T> 
vector<T*> fn(vector<T>& v) 
{ 
    vector<T*> r; 
    transform(v.begin(), v.end(), back_inserter(r), Address<T>()); 
    return r; 
} 


int main(void) 
{ 
    vector<int> a; 
    a.push_back(0); 
    fn(a); 
} 
+1

それを指摘した誰もが、それは間違いなく、有用な知識であるこの答えのおかげで、それはお粗末なものだったことを指摘した。 – Sam

6

することで、受信ベクトル:

std::vector<T*> fn(std::vector<T> &v) 
{ 
    std::vector<T*> r; 

    for (int i = 0; i < v.size(); i++) 
    { 
    r.push_back(&v[i]); 
    } 

    return r; 
} 

以下EDITより

すなわち容易になります。 vが成長した場合、ポインタが無効になることがあります。 r[i]は、&v[i]のエイリアスです。

実際にポインタを渡す必要がある場合(まだ理解できませんでした)、&v[0]とベクターのサイズを渡すことができます。 std::vectorのすべての実装では、ベクトルの要素がメモリに連続して格納されることを保証する必要があるため、最初の要素のアドレスとベクトルのサイズからすべてのアドレスを推定できます。

+0

真実ですが、私の(愚かな)ケースでは、ベクトルのサイズが一度変更され、その後ベクトルを返す必要があります。 – Sam

+0

@Sam:**なぜですか?** – GManNickG

1

これを行う標準ライブラリ機能はありません。

std::vector<T*> pv(v.size()); 
for (size_t i=0; i<v.size(); ++i) 
    pv[i] = &v[i]; 

は、おそらくC++ 0x lambdasを使用しない場合、このループの最も短い表現です。

+0

ください、繰り返しごとに 'サイズ'を求めないでください... – xtofl

+0

@xtofl:どうしてですか?あなたは本当にそれは任意のコストがあると思いますか? – GManNickG

+0

@xtofl:このような間違った動作をするプログラムでは、マイクロ最適化についてはあまり気にしません。 (しかしFYI:私のコンパイラはこれを最適化しています) –

1

あなたはの線に沿って何か行うことができます:

template <typename T> 
T* mk_ptr(T& t) { 
    return &t; 
} 

template <typename T> 
std::vector<T*> fn(std::vector<T>& v) { 
    std::vector<T*> r; 
    std::transform(v.begin(), v.end(), std::back_inserter(r), mk_ptr); 
    return r; 
} 

をしかし、一つは、このの動機について疑問に持っている...理由のためのイテレータがあります。誰もポインタが有効であることを保証しません。

1

まずあなたが正しい方法を見つける必要があります。あなたのコード(編集:元のコードvは値渡しです)は間違っており、未定義の動作が発生します。アプリケーションによっては、通常、pointer containerまたはsmart pointersを格納する通常のコンテナが必要です。

関連する問題