int power(int x) { return x * x; } int main() { int x = power(2); //cout << v.str[0] << endl; return 0; }
對於返回值比較偏小的函數,直接將返回值保存至寄存器。
這里先將x的值保存至eax中,在用imul指令計算x*x的值(eax = eax * x)。函數返回后直接從eax中取回結果。
如果結果比較大,無法將結果保存至寄存器中,那只能將結果的地址保存至寄存器中。
struct Node { char str[100]; }; Node fun() { Node n; n.str[0] = 'o'; return n; } int main() { Node x = fun(); return 0; }
首先觀察fun函數返回的過程:
使用rep movs將n按字節拷貝至rbp+170h的地址(拷貝的長度由ecx決定),將返回的地址保存至rax中。
再看獲取fun返回值的過程:
將返回的地址從rax中取出,再拷貝至x中。
也就是說這個過程將返回的結構體拷貝了2次。。。從n拷貝到temp,再從temp拷貝到x。
在C++11中提供了RVO/NRVO機制可以防止這種重復拷貝開銷。另一種是RVO/NRVO機制實現復制消除機制。
RVO機制使用父棧幀(或任意內存塊)來分配返回值的空間,來避免對返回值的復制。也就是將Base fun();改為void fun(Base &x);
Base fun(int n) { return Base(); } Base x = fun();
這段代碼輸出為:
Base()
~Base()
但如果代碼產生了改動,編譯器無法知道應該防止哪個對象作為返回值,就無法觸發RVO機制:
Base fun(int n) { Base a,b; if (n % 10 == 1) { return a; } else { return b; } }