#cpp #ассемблер
C++: #includeint main() { int a =10; int b = std::move(a); } ASM: std::remove_reference ::type&& std::move (int&): push rbp mov rbp, rsp mov QWORD PTR [rbp-8], rdi mov rax, QWORD PTR [rbp-8] pop rbp ret main: push rbp mov rbp, rsp sub rsp, 16 mov DWORD PTR [rbp-8], 10 lea rax, [rbp-8] mov rdi, rax call std::remove_reference ::type&& std::move (int&) mov eax, DWORD PTR [rax] mov DWORD PTR [rbp-4], eax mov eax, 0 leave ret Как семантика перемещения работает на уровне ассемблера?
Ответы
Ответ 1
Семантика перемещения - концепция уровня языка, построенная вокруг типа rvalue-ссылки, категории xvalue и связанных с этим типом правил разрешения перегрузок ("overload resolution"). На уровне ассемблера нет никакой разницы между rvalue-ссылкой и lvalue-ссылкой. Все фундаментальные типы всегда безусловно копируются, независимо того, является ли правая часть rvalue-ссылкой или нет. Для пользовательских же типов все определяется тем, что вы сами напишете в соответствующих перегруженных функциях. Что вы напишете - то и получится в ассемблере. Другими словами, нет никакой "семантики перемещения" на уровне ассемблера. На уровне ассемблера есть только копирование. А вам, пользователю языка, в рамках языковой "семантики перемещения" лишь дается возможность выбрать, что (и как) копировать, а что не копировать. В приведенном вами коде вы видите лишь не устраненный оптимизатором вызов функции std::move, которая "ничего не делает", а просто приводит свой аргумент к типу rvalue-ссылки. В коде, сгенерированном "начистовую" все эти "ничего не делающие" вызовы должны быть устранены и код должен быть эквивалентен простому int a = 10; int b = a; Например void foo(int &a, int &b, int &c, int &d) { a = std::move(b); c = d; } при компиляции g++ -O3 дает foo(int&, int&, int&, int&): // a = std::move(b); mov eax, DWORD PTR [rsi] mov DWORD PTR [rdi], eax // c = d; mov eax, DWORD PTR [rcx] mov DWORD PTR [rdx], eax // ret https://godbolt.org/z/O2WAmU
Комментариев нет:
Отправить комментарий