深入學習 C++ 臨時對象的執行個體教程

來源:互聯網
上載者:User

瞭解臨時對象的來源

c++真正的所謂的臨時對象是不可見的——不會再你的原始碼中出現。此等匿名對象通常發生於兩種情況:一是當隱式類型轉換(implicit type conveersions)被施行起來以求函數調用能夠成功;二是當函數返回對象的時候。

第一種情況的例子:

 代碼如下 複製代碼
#include <iostream>

class Int
{
public:
        Int(int value) {
                _value = value;
                std::cout << "In constructor, count: " << ++count << std::endl;
        }
        ~Int() {
                std::cout << "In destructorn";
        }

        int _value;
private:
        static int count;
};

int Int::count = 0;

void printInt(Int intValue) {
        std::cout << "int value is: " << intValue._value << std::endl;
}

int main()
{
        printInt(10);
        return 0;
}



這個例子的運行結果是:
In constructor, count: 1
int value is: 10
In destructor

驗證了編譯器再發現沒法調用printInt(int)的時候,會進行自動類型轉換,通過Int的建構函式,將int隱式轉換成Int(這個貌似之前也提到過了)。這個構造出來的就是所謂的臨時對象,從輸出的順序看,這個對象在函數返回之後被析構。

只有當對象以by value(傳值)方式傳遞,或是當對象被傳遞給一個reference-to -const參數時,這些轉換才會發生。如果參數被傳遞給一個reference-to-non-const參數,並不會發生此類轉換

也就是說,把上面的printInt入參改成Int&的時候,就無法調用成功。原因很簡單了,這個臨時對象,如果沒修改,函數返回之後也被析構了,沒法再次擷取到,即使允許也是沒意義的。改成Int&之後,編譯器(g++)有這樣的報錯:
tmp.cpp: 在函數‘int main()’中:
tmp.cpp:27:13: 錯誤:用類型為‘int’的右值初始化類型為‘Int&’的非常量引用無效
tmp.cpp:21:6: 錯誤:在傳遞‘void printInt(Int&)’的第 1 個實參時

利用重載(overload)避免隱式類型轉換(implicit type conversions)

這裡介紹的就是通過重載,避免編譯器自動通過建構函式建立臨時對象,但是重載太多後面的維護什麼的成本也會上升,需要考慮這個的必要性。

    每個“重載操作符”必須獲得至少一個“使用者定製類型”的自變數

協助完成傳回值最佳化(RVO)

另一個容易產生臨時對象的地方就是函數傳回值。不過經過嘗試,發現目前編譯器(g++)可以把命名變數也通過傳回值最佳化去除。
也就是說,這樣寫:

 代碼如下 複製代碼
#include <iostream>

class Int
{
public:
        Int(int value) {
                _value = value;
                std::cout << "In constructor, count: " << ++count << " value: " << _value <<std::endl;
        }
        Int(const Int &rhs) {
                _value = rhs._value;
                std::cout << "In copy constructor, count: " << ++count << " value: " << _value << std::endl;
        }


        friend const Int operator+(const Int &lhs, const Int &rhs);

private:
        int _value;
        static int count;
};

int Int::count = 0;
const Int operator+(const Int &lhs, const Int &rhs) {
        Int result(lhs._value + rhs._value);
        return result;
}

int main()
{
        Int a(1);
        Int b(2);
        Int c = a + b;

        return 0;
}



和這樣寫:

 代碼如下 複製代碼
#include <iostream>

class Int
{
public:
        Int(int value) {
                _value = value;
                std::cout << "In constructor, count: " << ++count << " value: " << _value <<std::endl;
        }
        Int(const Int &rhs) {
                _value = rhs._value;
                std::cout << "In copy constructor, count: " << ++count << " value: " << _value << std::endl;
        }


        friend const Int operator+(const Int &lhs, const Int &rhs);

private:
        int _value;
        static int count;
};

int Int::count = 0;
const Int operator+(const Int &lhs, const Int &rhs) {
        return Int(lhs._value + rhs._value);
}

int main()
{
        Int a(1);
        Int b(2);
        Int c = a + b;

        return 0;
}



最終的執行結果都是一樣的:

In constructor, count: 1 value: 1
In constructor, count: 2 value: 2
In constructor, count: 3 value: 3

沒有因為前者在operator+中多了一個result對象而多一個臨時變數。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.