herlack napisał(a)
tu otrzymasz chyba dwa kopiowania, albo i trzy - dla każdego operatora.
Nieprawda - akurat w tym wypadku GCC policzy wynik już w czasie kompilacji :P
Gdy używamy operacji 'na obiekcie', wtedy jest lepiej, np.:
a += b; // zamiast: a = a + b;
#include <iostream>
#include <complex>
typedef std::complex<int> comp;
int main()
{
comp a, b;
std::cin >> a >> b;
a = a+b;
return real(a);
}
g++ cpp.cpp -masm=intel -O2 -fverbose-asm -S
produkuje:
mov eax, DWORD PTR [esp+16] # tmp66, a._M_real
add eax, DWORD PTR [esp+24] # tmp66, MEM[(const int &)&b]
Zamiana na a += b
zwraca dokładnie to samo.
Przy dłuższych obliczeniach tego typu kompilator rezerwuje pełno tymczasowych zmiennych na stosie - dziesiątki!
d = a^2 * 2 + b*c - c^2;
d = sqrt(d) - 1 + log(c);
normalnie masakra z tego wyjdzie.
#include <iostream>
#include <complex>
int main()
{
std::complex<int> a, b, c, d;
std::cin >> a >> b >> c >> d;
d = a*a * 2 + b*c - c*c;
d = sqrt(d) - 1 + log(c);
return real(d);
}
Zwraca
mov esi, DWORD PTR [esp+64] # __r$_M_real, c._M_real
mov ebx, DWORD PTR [esp+68] # __r$_M_imag, c._M_imag
mov eax, esi #, __r$_M_real
imul eax, ebx #, __r$_M_imag
mov DWORD PTR [esp+36], eax # %sfp,
mov edx, DWORD PTR [esp+48] # __r$_M_real, a._M_real
mov ecx, DWORD PTR [esp+52] # D.24090, a._M_imag
imul ecx, edx # D.24090, __r$_M_real
mov eax, DWORD PTR [esp+56] # tmp109, b._M_real
imul eax, esi # tmp109, __r$_M_real
mov edi, DWORD PTR [esp+60] # tmp108, b._M_imag
imul edi, ebx # tmp108, __r$_M_imag
sub eax, edi # tmp109, tmp108
imul edx, edx # tmp112, __r$_M_real
mov edi, DWORD PTR [esp+52] # tmp111, a._M_imag
imul edi, edi # tmp111, tmp111
sub edx, edi # tmp112, tmp111
lea eax, [eax+edx*2] # tmp118,
mov edx, esi # tmp117, __r$_M_real
imul edx, esi # tmp117, __r$_M_real
mov edi, ebx # tmp116, __r$_M_imag
imul edi, ebx # tmp116, __r$_M_imag
sub edx, edi # tmp117, tmp116
sub eax, edx # tmp118, tmp117
mov DWORD PTR [esp+72], eax # d._M_real, tmp118
mov eax, DWORD PTR [esp+56] # tmp119, b._M_real
imul eax, ebx # tmp119, __r$_M_imag
mov edx, DWORD PTR [esp+60] # tmp120, b._M_imag
imul edx, esi # tmp120, __r$_M_real
add eax, edx # tmp121, tmp120
lea eax, [eax+ecx*4] # tmp126,
mov edx, DWORD PTR [esp+36] # tmp125, %sfp
sal edx # tmp125
sub eax, edx # tmp126, tmp125
mov DWORD PTR [esp+76], eax # d._M_imag, tmp126
mov DWORD PTR [esp+44], esi #, __r$_M_real
fild DWORD PTR [esp+44] #
fstp QWORD PTR [esp+8] #
mov DWORD PTR [esp+44], ebx #, __r$_M_imag
fild DWORD PTR [esp+44] #
fstp QWORD PTR [esp] #
call _atan2 #
fstp st(0) #
mov DWORD PTR [esp+80], esi # D.24138._M_real, __r$_M_real
mov DWORD PTR [esp+84], ebx # D.24138._M_imag, __r$_M_imag
lea eax, [esp+80] # tmp129,
mov DWORD PTR [esp], eax #, tmp129
call __ZSt13__complex_absIiET_RKSt7complexIS0_E #
mov DWORD PTR [esp+44], eax #, D.24137
fild DWORD PTR [esp+44] #
fstp QWORD PTR [esp] #
call _log #
mov eax, DWORD PTR [esp+72] # d._M_real, d._M_real
mov DWORD PTR [esp+88], eax # D.24146._M_real, d._M_real
mov eax, DWORD PTR [esp+76] # SR.38, d._M_imag
mov DWORD PTR [esp+92], eax # D.24146._M_imag, SR.38
lea eax, [esp+88] # tmp132,
mov DWORD PTR [esp], eax #, tmp132
fstp QWORD PTR [esp+16] #
call __ZSt14__complex_sqrtIiESt7complexIT_ERKS2_ #
fnstcw WORD PTR [esp+42] #
mov dx, WORD PTR [esp+42] # tmp138,
mov dh, 12 # tmp138,
mov WORD PTR [esp+40], dx #, tmp138
fld QWORD PTR [esp+16] #
fldcw WORD PTR [esp+40] #
fistp DWORD PTR [esp+44] #
fldcw WORD PTR [esp+42] #
mov edx, DWORD PTR [esp+44] # tmp134,
lea eax, [edx-1+eax] # tmp133,
lea esp, [ebp-12] #,
pop ebx #
.cfi_restore 3
pop esi #
.cfi_restore 6
pop edi #
.cfi_restore 7
pop ebp #
.cfi_def_cfa 4, 4
.cfi_restore 5
ret
.cfi_endproc
Czyli najgorzej nie jest, chyba nawet większy output był wygenerowany dla float-ów, aniżeli tego complex
:P