2009-04-14 9 views
3

私はいくつかのC++コードを書いています。これは、サイズが変化しているベクトルの束を操作し、したがって、常に再割り当てされています。C++では、どのようにしてベクトルへのポインタを取得できますか?

私は、これらのベクトルにベクトルを再配置した後でも有効な "ポインタ"を取得したいと考えています。より具体的には、これらの「ポインター」がどのベクトルを指しているのか、どのベクトルを指しているのかを覚えておきたいだけです。私が標準(* ptr)構文を使ってそれらを逆参照するとき、私は彼らに明白な検索をさせたいだけです。

明らかに、実際のポインタは再割り当て後に有効ではなく、再配置後もイテレータが有効ではないことがわかります。また、オブジェクトの前に要素が挿入されているかどうかは気にしないので、これらのポインタは実際にベクトルとインデックス以外のものを覚える必要はありません。

今、私はこのようなクラスを自分で簡単に書くことができました。誰か(Boost?STL?)はすでに私のためにそれをしていますか?

:答えは私の質問には対応していません。 この機能が標準ライブラリであるかどうか尋ねました。私は「ノー」と回答しますか?

+0

PSを。これが愚かで重複した質問であれば、誰かが参照を提供した場合は削除してもよろしいです。ありがとう! –

+0

std :: vector <>を使用できない理由はありますか? –

+0

明らかに、彼はベクトルだけでなくベクトル内の位置も保持したいからです。ベクタが決して再割り当てされなかった場合、イテレータが必要になります。 「考えてください」ベクトルバー; Myiterator mi(バー、3);だから* miは常にbar [3]になります。 –

答えて

22

ベクトルの位置も要素のインデックスも変化しないので、std :: pair <ベクトル*、int>を試してください。
あるいは、クラスのように:STLやブーストでもないが、簡単にそれを行うには何が含まれているよう

template<class T> class VectorElementPointer 
{ 
    vector<T>& vectorref; 
    typename vector<T>::size_type index; 
public: 
    VectorElementPointer(vector<T>& vref, typename vector<T>::size_type index):vectorref(vref),index(index){} 
    T& operator*() const {return vectorref[index];} 
    T* operator->() const {return &vectorref[index];} 
}; 

これは、私の心に来る最も簡単な解決策です。

+0

+1 - 私にそれを打つ。私が示唆したいのは、vectorptrをポインタの代わりに参照にすることです。 –

+0

+1。演算子 - >()を追加するといいかもしれません。 –

+0

他の演算子をお望みですか? – tstenner

1

残念なことに、いったんベクトルを変更すると、ベクトルの要素を「指す」イテレータはもはや有効であることが保証されなくなります。構造が変わってもイテレータを有効に保つSTL構造体はリスト<>です。 std :: list <を使用するよりも、構造の順次反復のみが必要な場合は、他のライブラリを知らないとわかりません。それがないというわけではありません。

ここではstd ::リストにいくつかの明確な文書があります:http://www.cplusplus.com/reference/stl/list/あなたはポインタが再割り当て後に有効になること方法はありませんベクトルとスマートポインタの独自のバージョンを作成しなければ

+0

マップとセットも有効なイテレータを保持します。 – gbjbaanb

0

。独自の実装がある場合、スマートベクトルはスマートポインタに通知を送信できます。

しかし、私はシナリオ全体が悪いデザインだと思っています。そのような要件がないようにシナリオを再設計するほうがよいかもしれません。

0

ご使用のパターンによっては、std :: dequeが必要条件を満たしている可能性があります。デキューへのポインタは、最初または最後にないアイテムを挿入または削除する場合にのみ無効になります。-pur_front()およびpush_back()は両端キューへのポインタを無効にしませんが、他の変更は行いません。基本的にはベクトルと同じインターフェースが得られますが、基本ストレージは連続していません。

+0

私は、誰かがこの答えを落としたことが奇妙に感じます。私の状況では、デキュー操作のみを使用していましたが、デキューへの深いポインタのプロパティは、私の質問に直接対処していなくても役立ちます。ほんとありがと! –

3

いくつかのアイデアをまとめます。イテレータを模倣しようとするが、ベクトルのものとは正反対に有効なミニマリストラッパーがあります。

void print(const std::string& i) 
{ 
    std::cout << "<" << i << "> "; 
} 
int main() 
{ 
    typedef std::vector<std::string> Vector; 

    Vector v; 
    v.push_back("H"); 
    v.push_back("E"); 
    v.push_back("W"); 
    StrongIterator<Vector> it0(v, 0); 
    StrongIterator<Vector> it3(v, v.end()); 

    std::for_each(it0.it(), it3.it(), print); 
    std::cout << std::endl; 

    v.push_back("O"); 
    std::for_each(it0.it(), it3.it(), print); 

    std::cout << *it0; 
    std::cout << it0->c_str(); 

    return 0; 
} 

そして、イテレータ自体。

boost::iterator_facade使用
template <typename TVector> 
class StrongIterator 
{ 
public: 
    typedef typename TVector::iterator iterator; 
    typedef typename TVector::size_type size_type; 
    typedef typename TVector::value_type value_type; 
    StrongIterator(TVector& vector, 
        size_type index): 
     vector_(vector), 
     index_(index) 
    {} 
    StrongIterator(TVector& vector, 
        iterator it): 
     vector_(vector), 
     index_(std::distance(vector.begin(), it)) 
    {} 
    iterator it() 
    { 
     iterator it = vector_.begin(); 
     std::advance(it, index_); 
     return it; 
    } 
    value_type& operator*() 
    { 
     return vector_[index_]; 
    } 
    value_type* operator->() 
    { 
     return &vector_[index_]; 
    } 
private: 
    TVector& vector_; 
    size_type index_; 
}; 
2

// Warning: Untested, not even compiled 
template<class VectorT> 
class VectorIndex : 
    public boost::iterator_facade<VectorIndex, typename VectorT::reference, boost::random_access_traversal_tag> 
{ 
public: 
    VectorIndex(VectorT& Vec, typename VectorT::size_type Index) 
    : m_Vec(Vec), m_Index(Index) 
    { 
    } 

private: 
    friend class boost::iterator_core_access; 

    void increment() 
    { 
     ++m_Index; 
    } 

    void decrement() 
    { 
     --m_Index; 
    } 

    void advance(difference_type N) 
    { 
     m_Index += N; 
    } 

    difference_type distance_to(const VectorIndex& Other) 
    { 
     assert(&this->m_Vec == &Other.m_Vec); 
     return Other.m_Index = this->m_Index; 
    } 

    bool equal(const VectorIndex& Other)const 
    { 
     return (this->m_Vec == Other.m_Vec) 
      && (this->m_Index == Other.m_Index); 
    } 

    VectorT::reference dereference() const 
    { 
     return m_Vec[m_Index]; 
    } 

    VectorT m_Vec; 
    VectorT::size_type m_Index; 
}; 
関連する問題