c++函數返回的過程


 

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;
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM