C++ jest określona w kategoriach operacji w stosunku do teoretycznego modelu pamięci komputera.
Posiada również funkcję znaną jako "jak gdyby".Oznacza to, że kompilator może generować dowolny kod, pod warunkiem, że ogólny obserwowalny efekt jest "taki, jak gdyby" kod, który napisałeś, został dosłownie przetłumaczony na operacje w stosunku do modelu pamięci.
W kodzie nieoptymalizowane, monter produkowane jest w rzeczywistości bardzo blisko do operacji wyrażonej w kodzie, na przykład gcc może produkować następujący kod dla funkcji:
a(int): # @a(int)
push rbp
mov rbp, rsp
mov dword ptr [rbp - 4], edi
mov edi, dword ptr [rbp - 4]
shl edi, 1
mov dword ptr [rbp - 8], edi
mov eax, dword ptr [rbp - 8]
pop rbp
ret
i biorąc pod uwagę następujący kod wywołujący:
extern void foo(int x);
int main()
{
foo(a(2));
}
następujący kod może być wytwarzane:
main: # @main
push rbp
mov rbp, rsp
mov edi, 2
call a(int)
mov edi, eax
call foo(int)
xor eax, eax
pop rbp
ret
W tym prostym programie, zauważalnym efektem kodu jest wywołanie foo
z argumentem o wartości 4. Połączenie z a
ma tylko jeden obserwowalny efekt uboczny. Oznacza to, że jego wartość zwracana jest dwukrotnie większa od wartości wejściowej.
Ponieważ zwracana wartość jest przekazywana bezpośrednio do foo
i nie są przechowywane w dowolnym miejscu, moglibyśmy powiedzieć, że wszystkie skutki uboczne nazywając a
są całkowicie zużywane przez wywołanie foo
.
Dlatego jeśli kompilator wie, co robi a
, nie musi generować kodu, aby go wywołać. Może po prostu zadzwonić pod numer foo
z wartością wyprowadzoną "tak jakby", wywołując a(2)
.
Rzeczywiście, dodając optymalizacji daje nam to:
main: # @main
push rax
mov edi, 4 # note: 'as if' a(2)
call foo(int)
xor eax, eax
pop rcx
ret
Realizacja a
w tym przypadku (na gcc) jest następujący:
a(int): # @a(int)
# 'as if' we created a variable and did some arithmetic,
# stored the result and then returned the result
lea eax, [rdi + rdi]
ret
Funkcja wywołująca po prostu użyje EAX (lub gdziekolwiek) – Caleth
Czy chcesz wiedzieć, co dzieje się w niezoptymalizowanym przypadku? Pytam, ponieważ wystarczająco dobry kompilator mógłby włączyć 'int foo = a (2);' do bezpośredniego inicjowania 'foo' z' 4'. – NathanOliver
Poinformuj kompilator, aby wyprowadził język asemblera dla funkcji. –