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

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

ИЗМЕНИТЬ

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


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


Ответы (4)


Операторы индекса 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 посчитали, что это слишком много волшебства.

person Marc Mutz - mmutz    schedule 15.07.2009
comment
Константный оператор нижнего индекса std::map... Но std::map не имеет оператора нижнего индекса const? - person CB Bailey; 30.07.2009
comment
они полностью запрещают вызовы с индексами, которых нет в контейнере, но вы можете сделать это на std::map, это один из способов вставки новых значений. Но даже если вы имели в виду в общем случае, как из этого следует, что они не предоставляют оператора индекса const? - person CiscoIPPhone; 31.07.2009
comment
Одно из рекомендаций по проектированию STL заключалось в том, чтобы не предоставлять операции, которые невозможны эффективным способом. Вот почему std::map не имеет оператора индекса const, а std::list вообще не имеет оператора индекса. - person Marc Mutz - mmutz; 31.07.2009
comment
хорошее замечание по поводу выполнения бинарного поиска дважды. Но что, если я знаю, что элементы существуют? Мне просто нужно знать, на что они сопоставляются... - person MadH; 03.08.2009
comment
Только для защитного программирования вы все равно добавите `assert( map.count( X ) ), и я видел слишком много программного обеспечения, поставляемого с включенными утверждениями, чтобы отклонить любое утверждение о том, что утверждения не критичны для производительности, как принятие желаемого за действительное. - person Marc Mutz - mmutz; 05.08.2009
comment
@MarcMutz-mmutz, могу я попросить вас взглянуть на этот вопрос по другой теме: stackoverflow.com/questions/11116963/ ? - person Istiaque Ahmed; 20.06.2012

В документации для 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
person Adam W    schedule 03.08.2009

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

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

person Martin B    schedule 14.07.2009
comment
Я бы предпочел, чтобы поведение оператора [] было таким же, как у метода std:: и value(), чтобы возвращать его по значению... - person MadH; 14.07.2009
comment
Хорошо, но почему const T QHash::value(const Key &key, const T &defaultValue) const не возвращает ссылку? - person Thomas Klier; 08.11.2017

Странно, да.

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

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

person unwind    schedule 14.07.2009