Есть идеи, почему QHash и QMap возвращают const T вместо const T &? - PullRequest
9 голосов
/ 14 июля 2009

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

EDIT

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

Ответы [ 4 ]

29 голосов
/ 15 июля 2009
Операторы индексов

const контейнеров STL могут возвращать ссылку на const, поскольку они отклоняют вызовы к нему с индексами, которых нет в контейнере. Поведение в этом случае не определено. Следовательно, как мудрый выбор дизайна, std::map даже не обеспечивает перегрузку оператора индекса const.

QMap пытается быть немного более приспособленным, предоставляет перегрузку оператора const в качестве синтаксического сахара, сталкивается с проблемой с несуществующими ключами, снова пытается быть более удобной и вместо этого возвращает значение, созданное по умолчанию.

Если вы хотите сохранить соглашение о возврате по константной ссылке в STL, вам нужно выделить статическое значение и вернуть ссылку на , что . Это, однако, противоречило бы гарантиям повторного входа, которые предоставляет QMap, поэтому единственный вариант - возврат по значению. У const есть только сахарное покрытие, чтобы предотвратить некоторые глупые ошибки, такие как constmap["foo"]++ от компиляции.

Тем не менее, возвращение по ссылке не всегда является наиболее эффективным способом. Если вы возвращаете фундаментальный тип или, при более агрессивной оптимизации, когда sizeof(T)<=sizeof(void*), возвращаемое значение часто заставляет компилятор возвращать результат в регистр напрямую, а не косвенно (адрес для результата в регистре) или - не дай бог - в стеке.

Другая причина (кроме преждевременной пессимизации) предпочитать передачу по константной ссылке, нарезку, здесь не применима, так как std::map и QMap основаны на значениях и, следовательно, однородны. Для гетерогенного контейнера вам нужно хранить указатели, а указатели являются фундаментальными типами (конечно, кроме умных).

Тем не менее, я почти никогда не использую оператор константного индекса в Qt. Да, он имеет более приятный синтаксис, чем find() + *it, но неизменно вы получите count() / contains() вызовов прямо перед оператором константного индекса, что означает, что вы выполняете бинарный поиск дважды . И тогда вы все равно не заметите крошечных различий в производительности возвращаемого значения:)

Для value() const, однако, я согласен, что он должен возвращать reference-to-const, по умолчанию передавая ссылку на default-value в качестве второго аргумента, но я думаю, разработчики Qt чувствовали, что это слишком много магия.

4 голосов
/ 03 августа 2009

В документации для QMap и QHash специально сказано, чтобы избегать operator[] для поиска по причине, указанной Мартином Б.

Если вы хотите использовать константную ссылку, используйте const_iterator find ( const Key & key ) const, где вы можете использовать любой из:

const Key & key () const
const T & value () const
const T & operator* () const
const T * operator-> () const
3 голосов
/ 14 июля 2009

На самом деле, некоторые методы do возвращают ссылку ... например, неконстантная версия operator[] возвращает T &.

Однако постоянная версия operator[] возвращает const T. Зачем? Как уже отмечалось, «размотка» связана с тем, что происходит, когда ключ не существует на карте. В неконстантном operator[] мы можем добавить ключ на карту, а затем вернуть ссылку на вновь добавленную запись. Однако const operator[] не может этого сделать, потому что не может изменить карту. Так что же он должен возвращать ссылку? Решение состоит в том, чтобы заставить const operator[] вернуть const T, а затем вернуть построенный по умолчанию T в случае, если ключ отсутствует на карте.

1 голос
/ 14 июля 2009

Странно, да.

Возможно, это из-за желаемой семантики, например, при выполнении. <a href="http://doc.qt.io/archives/4.6/qhash.html#value" rel="nofollow noreferrer">value()</a> для неопределенного ключа, возвращает значение по умолчанию правильного типа. Это невозможно при использовании ссылок, по крайней мере, не так чисто.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...