Давайте рассмотрим этот класс:
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
и Statement 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 (/* [...] */)
Следует отметить, что класс *У 1016 * есть некоторые серьезные проблемы с дизайном:
_map
следует лучше инкапсулировать внутри класса (как для чтения, так и для доступа к записи), чтобы можно было избежать метода getTheMap()
- Если метод
getTheMap()
действительно необходим, он может вернуть ссылку на _map
Однако, учитывая класс X "как есть" (<- см. Правку ниже), есть лиспособ запретить пользователям переходить во временный итератор? </p>
EDIT: класс X
можно изменить, но метод getTheMap
должен существовать и возвращаться по значению.однако я также думал о предупреждениях компилятора.