Z>Вы куда-то контекст обсуждения потеряли.
Z>Естественно функция которую не вызывают вообще самая быстрая,
Z>можно считать что она вызывается за 0 тактов.
Z>Но мы же хотим чтобы в вся программа при использовании того или иного
Z>способа возврата string_view работала быстрее.
Z>Поэтому нужно рассматривать функцию возвращающую string_view вместе
Z>с кодом который ее вызывает.
Z>И я вижу два варианта:
Z>Z>string_view_ref_or_value get_string_view();
Z>string_view_ref_or_value x = get_string_view();
Z>
Z>либо мы сразу используем x, тогда мы лезем в память и достаем
Z>и data и size (1), или передаем полученный x куда-то, но как мы выяснили
Z>передачу лучше делать по значению, значит мы снова лезем в память и опять же достаем
Z>data и size (2) (можно конечно дальше передавать ссылку, что кстати очень опасно,
Z>но в конце концов мы придем к 1 или 2).
А если мы передаём одни ссылки то нам не нужно доставать data и size до функции, где реально они будут нужны.
Скажем, в цепочке f->g->h->i мы можем создать объект в f и передавать ссылку до i, и только там достать data и size;
Если передавать по значению получается нужно их доставать и передавать каждый раз.
Или есть подвох ?
Z>В обоих случаях получается что либо одинаково быстро будет
Z>работать вся программа или чуть медленнее, если string_view вычисляется,
Z>потому кладется в поле класса, а потом на поле класса возвращается ссылка.
Т.е. если возвращать заранее созданный string_view как в случае поле класса то ссылка будет эффективней чем возвращать по значению ? Так ?
Здравствуйте, _NN_, Вы писали:
Z>>И я вижу два варианта:
Z>>Z>>string_view_ref_or_value get_string_view();
Z>>string_view_ref_or_value x = get_string_view();
Z>>
Z>>либо мы сразу используем x, тогда мы лезем в память и достаем
Z>>и data и size (1), или передаем полученный x куда-то, но как мы выяснили
Z>>передачу лучше делать по значению, значит мы снова лезем в память и опять же достаем
Z>>data и size (2) (можно конечно дальше передавать ссылку, что кстати очень опасно,
Z>>но в конце концов мы придем к 1 или 2).
_NN>А если мы передаём одни ссылки то нам не нужно доставать data и size до функции, где реально они будут нужны.
_NN>Скажем, в цепочке f->g->h->i мы можем создать объект в f и передавать ссылку до i, и только там достать data и size;
_NN>Если передавать по значению получается нужно их доставать и передавать каждый раз.
_NN>Или есть подвох ?
Ничего не понял,
если есть цепочка возврата, то какая разница заняты два регистра или один?
каждый раз это просто "ret", зачем кого-то доставать?
"f" заполняет два регистра и вызвает "ret", "g" уже имеет правильно заполненные регистры,
поэтому она просто вызывает ret, как и "h" и "i" сразу их использует.
Z>>В обоих случаях получается что либо одинаково быстро будет
Z>>работать вся программа или чуть медленнее, если string_view вычисляется,
Z>>потому кладется в поле класса, а потом на поле класса возвращается ссылка.
_NN>Т.е. если возвращать заранее созданный string_view как в случае поле класса то ссылка будет эффективней чем возвращать по значению ? Так ?
Нет, будет так же или хуже при возврате по ссылке. Хуже потому что если мы где-то будет иметь код
вида:
const string_view &another_get_string_view()
{
const string_view& s = get_string_view();
work_with_s_1(s);
global_function();
work_with_s_2(s);
return s;
}
то так как мы получили "s" по ссылке, то мы два раза перечитаем "data" и "size"
из памяти, так как может global_function поменяла данные по ссылке.
То есть если мы предаем не используя, то есть у нас прямая цепочка
h() { return g(); } g() { return f(); }
то будет также, потому что хотя мы используем два регистра,
а не один, но это ведь "конец" всех этих функций,
и регистры не нужно на стек сохранять,
а если мы между делом, что-то делаем с этим 'const string_view&' то будет хуже.
И как бы нужно не забывать, что string_view это по сути ссылка,
и она может быть получена от std::string,
и чем дальше мы отдаем string_view, тем сложнее следить за временем жизни,
передавать на несколько уровней вверх без использования string_view это
по-моему очень странный сценарий.
Здравствуйте, Zhendos, Вы писали:
Z>то будет также, потому что хотя мы используем два регистра,
Z>а не один, но это ведь "конец" всех этих функций,
Z>и регистры не нужно на стек сохранять,
Z>а если мы между делом, что-то делаем с этим 'const string_view&' то будет хуже.
MSVC судя по всему не очень доволен передачей по значению.
Получаем копирование из памяти вместо использование регистров:
mov rdi, QWORD PTR __$ReturnUdt$[rsp]
mov rsi, rax
mov ecx, 16
rep movsb
https://gcc.godbolt.org/z/bEiWGU
Здравствуйте, _NN_, Вы писали:
_NN>Здравствуйте, Zhendos, Вы писали:
Z>>то будет также, потому что хотя мы используем два регистра,
Z>>а не один, но это ведь "конец" всех этих функций,
Z>>и регистры не нужно на стек сохранять,
Z>>а если мы между делом, что-то делаем с этим 'const string_view&' то будет хуже.
_NN>MSVC судя по всему не очень доволен передачей по значению.
_NN>https://gcc.godbolt.org/z/bEiWGU
1. Не inline бесмысленна в этом коде, функция должна быть extern,
то есть ее тело должно быть невидимым для компилятор в этой единице трансляции
2. Нужно конечно в godbolt поменять компилятор на любой другой: icc, clang, gcc
Ведь в том ABI в x86-64 который реализовала MS весь спор о передаче по ссылке 16 байт
или по значению, а также возврат по ссылке 16 байт или по значению полностью бессмыслен,
разве это не очевидно?