これまでのすべての回答は、それを正しく行う方法を示していますが、コードが機能しない理由をさらに詳しく説明したいと思います。他の人が指摘したように、あなたの「ゲッター」はリストを値で返しています。これは (主に) C++ に固有のものです。プログラマーは、オブジェクトを値渡しするか参照渡しするかを明示的に指定する必要があります。Java などの他のプログラミング言語は、(ほとんど) 常に参照渡しになります。次のように変数を割り当てるとします。
MyClass a;
MyClass b = a;
多くの言語では、割り当ては次のことを意味します。 をb
指す参照を作成しa
ます。その後、 でメソッドを呼び出すことができb
、 であるかのように動作しますa
。
一方、C++ では、次のことを意味しb
ます。これは、すべての要素が新しく作成されたリストにコピーされることを意味します! (これは、他の影響に加えて、パフォーマンスの問題になる可能性があります)。a
b
一方、コンパイラに a への参照を作成するように指示した場合:
MyClass& b = a;
次に、これb
は実際に であるかのように動作します。状態はコピーされず、変更b
すると変更されますa
。
さて、コード例に戻りましょう。最初のバージョンでは、次の行があります。
// Creates an invalid iterator!
std::list<OtherClass *>::iterator itB = inst.getL().begin();
それは実際にはそこにあるさまざまなものの束です。を呼び出すとinst.getL()
、新しいリストが作成され、inst
のリスト メンバーのすべての内容がそのリストにコピーされます。次に、そのコピーへの反復子を取得します。その後、コピー自体が破棄され、イテレータが無効になります。なんで?リストのコピーを何にも割り当てていないためです。C++ では、new
スコープ外になるスタック割り当てオブジェクト (つまり、 を使用して作成されていない) は破棄されます。簡単に言えば、「スコープ外」は、オブジェクトがその名前でアクセスできなくなるとすぐに発生します。
{ // Begin scope
MyClass o;
// Inside the braces, it's possible to refer to o:
o.doSomething();
} // End scope
o.doSomething() // Will be an error, as o is not "known" anymore
これは、次のように関数の戻り値を破棄した場合にも発生します。
inst.getL();
これにより、リストのコピーが作成され、再び破棄されます。
では、なぜ 2 番目の例が機能するのでしょうか。リストのコピーを一時変数に割り当てるため、それらはスコープ内にとどまります。
std::list<OtherClass *> l = inst.getL();
「getter」呼び出しからの一時オブジェクトはl
(今のところ代入演算子、RVO などを無視して) に格納され、取得されたすべてのイテレータは範囲外にl
なるまで有効になります。l
std::list<OtherClass *>::iterator itB = l.begin(); // valid
したがって、おそらく期待どおりではありませんが、これは機能します。イテレータは、実際のデータではなく、リストのコピーを操作しています。これは時々あなたが望むものかもしれませんが、あなたの場合、他の回答で示唆されているように参照が必要です。
これがあなたのためにそれを少し片付けるのに役立ったことを願っています.