このクラスを考えてみましょう:
class X {
std::map<uint32_t, uint32_t> _map;
public:
X() { /* Populate the map */ }
std::map<uint32_t, uint32_t> getTheMap() { return _map; }
};
そしてこのバグのあるコード:
X x;
// Statement 1
std::map<uint32_t, uint32_t>::const_iterator it = x.getTheMap().begin();
// Statement 2
std::map<uint32_t, uint32_t>::const_iterator et = x.getTheMap().end();
for (; it != et; it++) {
/* Access the map using the iterator it */
}
間違った部分は、Statement 1andStatement 2で、各ステートメントの最後に破棄される一時オブジェクトへのイテレータを取得していることです。その結果、for()ループ内の動作は未定義です。
メソッドの正しい使用getTheMap()法は次のとおりです。
std::map<uint32_t, uint32_t> map = x.getTheMap();
std::map<uint32_t, uint32_t>::const_iterator it = map.begin();
std::map<uint32_t, uint32_t>::const_iterator et = map.end();
for (/* [...] */)
Xクラスにはいくつかの重大な設計上の問題があることに注意する必要があります。
_mapクラス内に(読み取りアクセスと書き込みアクセスの両方で)より適切にカプセル化する必要があるため、getTheMap()メソッドを回避できます- メソッドが本当に必要な場合は
getTheMap()、への参照を返すことができます。_map
ただし、クラス X が「そのまま」(<-- 以下の編集を参照) の場合、ユーザーがイテレータを一時的に取得できないようにする方法はありますか?
編集: クラスXは変更できますが、getTheMapメソッドが存在し、値によって返される必要があります。ただし、コンパイラの警告についても考えていました。