C 深度解析 15 避免臨時物件

2021-10-02 10:50:04 字數 1733 閱讀 7787

2 編譯器會減少臨時物件

3 小結

首先,我們先看一段**,我們使用帶引數的建構函式實現不帶引數的建構函式

#include

class

test

test()

~test()

void

print()

private

:int x;};

intmain()

不帶引數的構造函式呼叫了帶引數的建構函式,將 x 初始化為 0。

編譯執行:

$ g++ 15-1.cpp -o 15-1

$ ./15-1

~test()

x = 21928

~test()

我們可以看到,類的成員變數 x 並沒有被初始化為 0,而是隨機值。並且呼叫了兩次析構函式。這是為什麼呢?

解析:那對於上面的**,如果初始化工作非常複雜,我們又想實現**復用,應該怎麼辦呢?

一般我們會宣告乙個私有的成員函式完成初始化,讓構造函式呼叫它。

#include

class

test

test()

~test()

void

print()

private

:int x;

void

init

(int i)};

intmain()

定義私有初始化函式 init(),然後不同的構造函式呼叫初始化函式。

$ g++ 15-2.cpp -o 15-2

$ ./15-2

x = 0

~test()

建構函式可能會非常大,減少臨時物件可以減少呼叫建構函式,提高效率。

下面看一示例:

// 15-3.cpp

#include

class

test

test()

:x(0

)test

(const test& t)

void

print()

~test()

private

:int x;};

test func()

intmain()

上面的**很簡單,主要是為了說明現代的 c++ 編譯器盡力減少臨時物件的產生。

第 36 行,直接使用 test(10) 將產生乙個臨時物件,再賦值給 t 又會呼叫拷貝建構函式。

函式 func() 產生乙個臨時物件並返回,將返回物件賦值給 tt,也將呼叫拷貝建構函式。

但是,實際上 g++ 編譯器經過優化,這裡避免了臨時物件的產生,也不會呼叫拷貝建構函式。所以:

第 36 行等價於 test t = 10;

第 37 行等價於 test tt = 20;

$ g++ 15-3.cpp -o 15-3

$ ./15-3

test(int):10

test(int):20

x = 10

x = 20

~test()

~test()

1、直接呼叫建構函式將產生乙個臨時物件

2、臨時物件是效能瓶頸,也是 bug **,現在 c++ 編譯器會盡力避開臨時物件

避免產生臨時 隱式 物件

產生乙個物件,如果這個物件很大並且這個物件是在乙個迴圈裡面產生的,是特別耗資源的,因為編譯器要找到一塊合適的記憶體,如果沒有合適的還要整理磁碟碎片並合併為一塊合適的物件儲存區。因此,在程式設計中一定要小心的產生臨時物件。臨時物件在c 語言中的特徵是未出現在源 中,從堆疊中產生的未命名物件。這裡需要特...

解析區域性物件與臨時物件

沒有名字的物件就是臨時物件,它存在於完整的表示式的生存其間。也就是說,當表示式計算結束後就會被釋放。乙個例外是,當臨時物件被引用時,它的生存期將延長到與這個引用的生存期一樣長。區域性物件就是可見區域在乙個函式範圍的物件。區域性物件有兩種,靜態區域性物件的生存期起於所在函式第一次被呼叫,結束於main...

C 臨時物件

臨時物件的產生 1.用建構函式作為隱式型別轉換函式時。2.建立乙個沒有名字的物件時。直接寫下 ctempobj 輸出 init obj exit obj 不單調用了建構函式,還呼叫了析構函式.既然是物件也可以這樣使用 ctempobj fun 不過這樣使用可要小心了 new ctempobj fun...