2009-09-07 4 views
6

C++ STLコンテナを使用する場合、参照条件に値をアクセスする必要がある条件はありますか。 たとえば、次の関数呼び出し後に無効にされた参照はありますか?STLコンテナ内の永続参照

{ 
std::vector<int> vector; 
vector.push_back (1); 
vector.push_back (2); 
vector.push_back (3); 

vector[0] = 10;  //modifies 0'th element 

int& ref = vector[0]; 
ref = 10;    //modifies 0'th element 

vector.push_back (4); 
ref = 20;    //modifies 0'th element??? 

vector.clear(); 
ref = 30;    //clearly obsurd 
} 

私はstlのほとんどの実装でこれがうまくいくことを理解していますが、私は標準宣言に必要なものに興味があります。

--edit:私は、C++用のSTXXL(http://stxxl.sourceforge.net/)ライブラリを試してみたかったが、私はコンテナによって返された参照は変更を加えずに読み込み、複数の上に永続的ではありませんでした、そのための互換性がないことに気づいたbecuase イム興味(しかし、表面的)私の既存のstlコードに。例:

{ 
std::vector<int> vector; 
vector.push_back (1); 
vector.push_back (2); 


int& refA = vector[0]; 
int& refB = vector[1]; //refA is not gaurenteed to be valid anymore 
} 

私は、これは確かにない、100%の互換性、またはSTXXLコンテナは、私が危険な/実装に依存する方法で、全体の時間をSTLコンテナを使用していた場合ことを意味している場合を知りたいと思いました。

+2

よくある質問http://algo2.iti.uni-karlsruhe.de/dementiev/stxxl/trunk/FAQ.html「外部メモリのデータ構造内の要素への参照を渡すべきではありません参照が使用されている場合、要素を含むブロックは内部メモリに存在しなくなる可能性があります。 "という回答がNOであるため、コンテナ要素の参照はSTLの対応と同じではありません。 – Akusete

+1

C++標準を見てみると、すべてのコンテナはtypedefsの 'reference'、' const_reference'、 'pointer'と' const_pointer'を持っています。これらは基本となるアロケータの対応するtypedefにセットされています。標準委員会は最初、refsとポインタの抽象化を設定したいので、これらのものでもコンテナ(プロキシを使用している方法で)で「管理」することができましたが、途中で停止しました'allocator :: pointer'の型が' T * 'などであることを標準で規定しているので、typedef自体は最終的には無意味です。 –

+0

私はほとんどのSTLコンテナのインターフェイスを読み込んで同じ感覚を持っていましたが、なぜそれらが半分にしかならなかったのかについてのディスカッションを見つけることができませんでした。 – Akusete

答えて

12

は、標準では23.2.4.3/1で述べている: 新しいサイズが古い 容量よりも大きい場合

は[insert()]再割り当てが発生します。再割り当てが発生しない場合は、 イテレータと参照 を参照してから、挿入ポイントは のままです。これは、実際には、これは話が

は(約insert()、表68は、a.push_back(x)が任意のベクターaxためa.insert(a.end(), x)と同等でなければならないことを示しています。これは、reserve()のメモリがあらかじめ十分な場合、またはpush_back()以上のアイテムがある場合、イテレータと参照が無効にならないことが保証されていることを意味します。アイテムの削除について

は、23.2.4.3/3は言う:

[erase()]消去の ポイントの後のすべての イテレータと参照を無効にします。

それぞれ表68および表67によれば、pop_back()clear()erase()への適切な呼び出しに相当します。

+0

まあ、ディスクバックアップされたコンテナの100%STL互換の実装を実装することはできないと思います。 – Akusete

+1

参照を自由に作成して保持できるようにしたい場合は、そうは思わないでしょう。しかし、私の考えでは、別のデータ構造に存在するアイテムへの長期間の参照を保つことは、 "iffy"の練習です。代わりにイテレータを保持するだけの理由がありますか? –

+0

コンテナ内の構造体に複数の変更を加えたい場合は、しばしば(おそらく悪い習慣で)参照を取得してから、参照を変更します。毎回コンテナを通ってアクセスするよりも効果的です(特に樹木ベースのコンテナを使用する場合)。その後、ローカルコピーを作成して後で書き戻すよりも効果的です。 ...そのようなウサギで、私の知る限りの参考文献の有効な使用であったので、私はその使用が重大なエラーを引き起こすライブラリを使用するのに疲れていた(それはまた検出不能になるだろう) – Akusete

1

私は(capacity、またmax_sizeを参照してください、そしてreserve方法)の参照のみを明示的または暗示的なresize()によって無効化されることを期待しています。

+0

同意します。なぜclear()はメモリを無効にするのでしょうか?単にnullに設定するか、それと同様です。 – jkeys

+0

@Hooked:その動作に依存することは不可能です。 C++の標準ライブラリ実装は、2003 C++ ISO標準に定められているセマンティックルールに従えば、自由に自由に操作できます。 –

1

Vectorは、現在の容量に応じて、再割り当て時に反復子と参照を無効にします。上記のコードは、場合によっては機能するかもしれませんが、push_back(4)呼び出しの後で参照が無効になる可能性があるので、これに頼るべきではありません。

7

ベクトルのためのいくつかの基本的なルール:

  • 再割り当てはすべて 参照、ポインタ、ベクトルの要素のためのイテレータ が無効になります。
  • 挿入ポインタ、イテレータ、 無効にすることができます。
  • 要素の挿入または削除 要素を参照する参照、ポインタ、および イテレータが無効になります。
  • 挿入によって再割り当てが発生すると、 はすべての参照、 イテレータ、およびポインタを無効にします。ベクターに挿入について
+1

*十分なスペースを確保している場合は、挿入時に再割り当てが行われないことが保証されています(おそらく明らかですが重要です)。 –

関連する問題