このクラスを考えてみましょう:
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 1
andStatement 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
メソッドが存在し、値によって返される必要があります。ただし、コンパイラの警告についても考えていました。