Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Есть идеи, почему QHash и QMap возвращают const T вместо const T&?

Автор вопроса: MadHОтветов: 4

В отличие от std::map и std::hash_map, соответствующие версии в Qt не возвращают ссылку. Разве это не неэффективно, если я создам хеш для довольно громоздкого класса?

ИЗМЕНИТЬ

тем более, что есть отдельный метод value(), который потом мог бы вернуть его по значению.

  • Возможный дубликат Почему QMap::operator[](const Key & key ) вернуть по значению? Thomas Klier 06.11.2017
  • @ThomasKlier уверен, просто спросил 5 лет назад MadH 08.11.2017

c++referenceqtperformancehash

Ответы

Ответ 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() для неопределенного ключа возвращает построенное по умолчанию значение надлежащего типа. Это невозможно с использованием ссылок, по крайней мере, не так чисто.

Кроме того, такие вещи, как оптимизация возвращаемого значения имени, могут уменьшить влияние этой конструкции на производительность.

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы