#опытным
Небольшие типы данных, особенно до 8 байт длиной, быстрее передавать в методы или возвращать из методов по значению.
С помощью deducing this мы можем вызывать методы не для ссылки(под капотом которой указатель), а для значения объекта.
Семантика будет ровно такая, как вы ожидаете. Объект скопируется внутрь метода и все операции будут происходить над копией.
Давайте посмотрим на пример:
struct just_a_little_guy {
int how_small;
int uwu();
};
int main() {
just_a_little_guy tiny_tim{42};
return tiny_tim.uwu();
}Здесь используется старая нотация с неявным this.
Посмотрим, какой код может нам выдать компилятор:
sub rsp, 40
lea rcx, QWORD PTR tiny_tim$[rsp]
mov DWORD PTR tiny_tim$[rsp], 42
call int just_a_little_guy::uwu(void)
add rsp, 40
ret 0
Пройдемся по строчкам и посмотрим, что тут происходит:
- первая строчка аллоцирует 40 байт на стеке. 4 байта для объекта tiny_tim, 32 байта теневого пространства для метода uwu и 4 байта паддинга.
- инструкция lea загружает адрес tiny_tim в регистр rcx, в котором метод uwu ожидает свой неявный параметр.
- mov помещает число 42 в поле объекта tiny_tim.
- вызываем функцию-метод uwu
- наконец деаллоцируем памяти и выходим из main
А теперь применим deducing this с параметром по значению и посмотрим на ассемблер:
struct just_a_little_guy {
int how_small;
int uwu(this just_a_little_guy);
};Ассемблер:
mov ecx, 42
jmp static int just_a_little_guy::uwu(this just_a_little_guy)
Мы переместили 42 в нужный регистр и сразу же прыгнули в функцию uwu, а не вызвали ее. Поскольку мы не передаем объект в метод по ссылке, нам ничего не нужно аллоцировать на стеке. А значит и деаллоцировать ничего не нужно. Раз нам не нужно за собой подчищать, то можно просто прыгнуть в функцию и не возвращаться оттуда.
Конечно, это искусственный пример, оптимизация есть и мы можем в целом ожидать, то объекты маленьких типов можно быстрее обрабатывать с помощью deducing this.
Optimize yourself. Stay cool.
#cpp23 #optimization #compiler