В отличие от std::map и std::hash_map, соответствующие версии в Qt не возвращают ссылку. Разве это не неэффективно, если я создам хеш для довольно громоздкого класса?
ИЗМЕНИТЬ
тем более, что есть отдельный метод value(), который потом мог бы вернуть его по значению.
Ответ 1 · рейтинг 29 · Marc Mutz - mmutz
Операторы индекса const контейнеров STL могут возвращать ссылку на константу, потому что они полностью запрещают вызовы к нему с индексами, которые не существуют в контейнере. Поведение в этом случае не определено. Следовательно, как мудрый выбор дизайна, std::map даже не обеспечивает перегрузку оператора const subscript.
QMap пытается быть немного более уступчивым, предоставляет перегрузку оператора const subscript в качестве синтаксического сахара, сталкивается с проблемой несуществующих ключей, снова пытается быть более уступчивым и вместо этого возвращает значение, построенное по умолчанию.
Если вы хотите сохранить соглашение STL о возврате по константной ссылке, вам нужно выделить статическое значение и вернуть ссылку на это. Это, однако, противоречило бы гарантиям повторного входа, которые предоставляет QMap, поэтому единственный вариант - возврат по значению. const есть просто сахарная глазурь, чтобы предотвратить некоторые глупые ошибки, такие как constmap["foo"]++, от компиляции.
Тем не менее, возврат по ссылке не всегда самый эффективный способ. Если вы возвращаете фундаментальный тип или, с более агрессивной оптимизацией, когда sizeof(T)<=sizeof(void*), возврат по значению часто заставляет компилятор возвращать результат в регистр напрямую, а не косвенно (адрес для результата в регистре) или - не дай бог - на куча.
Другая причина (помимо преждевременной пессимизации) предпочтения передачи по константной ссылке, нарезка, здесь неприменима, поскольку и std::map, и QMap основаны на значениях и, следовательно, однородны. Для гетерогенного контейнера вам нужно будет хранить указатели, а указатели - это фундаментальные типы (конечно, за исключением интеллектуальных).
Тем не менее, я почти никогда не использую оператор индекса const в Qt. Да, у него более приятный синтаксис, чем у find()+*it, но неизменно вы получите вызовы count()/contains() прямо перед оператором индекса const, что означает, что вы выполняете двоичный поиск дважды. . И тогда вы все равно не заметите незначительных различий в производительности возвращаемого значения :)
Тем не менее, для value() const я согласен с тем, что он должен возвращать ссылку на константу, по умолчанию ссылка на значение по умолчанию передается в качестве второго аргумента, но я думаю, что разработчики Qt посчитали, что это слишком много волшебства.
Ответ 2 · рейтинг 4 · Adam W
В документации для QMap и QHash специально указано избегать operator[] для поиска по причине, указанной Мартином Б.
Если вам нужна ссылка на const, используйте const_iterator find ( const Key & key ) const, где вы можете использовать любой из:
const Key & key () const
const T & value () const
const T & operator* () const
const T * operator-> () const
Ответ 3 · рейтинг 3 · Martin B
На самом деле, некоторые из методов do возвращают ссылку... например, неконстантная версия operator[] возвращает T &.
Однако константная версия operator[] возвращает const T. Почему? Как уже отмечалось в "unwind", причина связана с тем, что происходит, когда ключ не существует на карте. В неконстантном operator[] мы можем добавить ключ на карту, а затем вернуть ссылку на вновь добавленную запись. Однако константа operator[] не может этого сделать, потому что не может изменять карту. Итак, на что он должен возвращать ссылку? Решение состоит в том, чтобы заставить константу operator[] возвращать const T, а затем возвращать построенную по умолчанию T в случае, когда ключ отсутствует на карте.
Ответ 4 · рейтинг 1 · unwind
Странно, да.
Возможно, это из-за желаемой семантики, где, например. value() для неопределенного ключа возвращает построенное по умолчанию значение надлежащего типа. Это невозможно с использованием ссылок, по крайней мере, не так чисто.
Кроме того, такие вещи, как оптимизация возвращаемого значения имени, могут уменьшить влияние этой конструкции на производительность.