Почему передача QStringView по значению быстрее, чем ссылка на const? - PullRequest
0 голосов
/ 17 сентября 2018

Я нашел это в Документе Qt :

QStringViews должны передаваться по значению, а не по ссылке на const:

и они приводят следующий пример:

void myfun1(QStringView sv);        // preferred
void myfun2(const QStringView &sv); // compiles and works, but slower

Как это возможно?

Ответы [ 2 ]

0 голосов
/ 02 июня 2019

QStringView обычно используется в высокопроизводительном коде, где создание реальных QString объектов будет медленным из-за задействованного выделения памяти.Я оптимизировал QStringView так, чтобы он работал так же быстро, как обрабатывал (const QChar*, size_t) вручную.Я даже дошел до того, что вызовы функций-членов передавались в линию свободным функциям, передавая значение *this.Все это состоит в том, чтобы избежать форсирования QStringView объектов в стек или, в более общем смысле, в память.

Практически во всех компиляторах C ++ объект QStringView представлен в виде пары регистров ЦП, и многиеABI C ++ (к сожалению, за исключением Windows) поддерживают передачу таких типов в регистрах ЦП в функции.Если вы написали функцию-член наивно, с неявным параметром this в качестве адреса объекта, то вызов такой функции вне строки вынудил бы компилятор выделить объект QStringView настек, чтобы иметь возможность передавать свой адрес в качестве первого аргумента функции-члена.

Есть второй аргумент для передачи по значению: меньше проблем с наложением.В качестве ссылочного типа, в любом случае, QStringView демонстрирует эту проблему, но рассмотрим std::complex: возьмите

std::complex &operator*=(std::complex &lhs, const std::complex &rhs);

(для краткости аргументы шаблона опущены).Это можно назвать так:

std::complex c = 3 + 4i;
c *= c;

Если вы наивно реализуете operator*=, как если бы это была математическая функция:

auto r = real(), i = imag();
m_real = r * other.real() - i * other.imag();
m_imag = r * other.imag() + i * other.real();

вы бы забили other.real() после первоголиния, таким образом вычисляя неправильный результат (да, люди делают пишут этот код в производстве).Передача rhs по значению устраняет проблему.

0 голосов
/ 17 сентября 2018

Они говорят в документах, что это должно быть передано по значению, потому что QStringView не является самой строкой, это просто своего рода интерфейс (ну, поэтому он называется «представление»), предоставляя вам доступ для чтения к указанной строке. Поэтому, скорее всего, размер QStringView аналогичен размеру ссылки. Согласно исходному коду QT, QStringView имеет только 2 поля:

private:
    qsizetype m_size;
    const storage_type *m_data;

На моей машине Debian9 x64 с gcc 6.3 размер этого класса составляет 8 (указатель) + 4 (целое число) = 12 байт. В моем случае эталонный размер составляет 8 байт, поэтому разница в копировании данных при вызове функции незначительна. Просто помните, что на разных машинах ссылки могут быть реализованы по-другому и могут быть больше.

Хотя я согласен, что этот вид интерфейса должен передаваться копией (не const ref), я не понимаю, почему они утверждают, что передача его через const ref на самом деле МЕДЛЕННА (разыменование переменной дважды на самом деле не имеет любой наблюдаемый эффект в современных приложениях). Мне бы очень хотелось, чтобы какой-то тест подтвердил это утверждение.

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