Какие-либо идеи, почему QHash и QMap возвращают константу T вместо константы T&?

Легко сериализируйте объекты в XML:

public static string ToXml<T>(this T obj) where T : class
{
    XmlSerializer s = new XmlSerializer(obj.GetType());
    using (StringWriter writer = new StringWriter())
    {
        s.Serialize(writer, obj);
        return writer.ToString();
    }
}

"<root><child>foo</child</root>".ToXml<MyCustomType>();
9
задан MadH 30 July 2009 в 11:19
поделиться

4 ответа

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

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

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

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

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

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

Однако для value () const я согласен, что он должен возвращать ссылку на- const,

29
ответ дан 4 December 2019 в 06:30
поделиться

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

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

3
ответ дан 4 December 2019 в 06:30
поделиться

Странно, да.

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

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

1
ответ дан 4 December 2019 в 06:30
поделиться

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

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

const Key & key () const
const T & value () const
const T & operator* () const
const T * operator-> () const
4
ответ дан 4 December 2019 в 06:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: