2013-05-12 78 views
6

我有以下兩個功能:爲什麼我的複製構造函數只在這種情況下調用兩次?

Class foo(Class arg) 
{ 
    return arg; 
} 

Class bar(Class *arg) 
{ 
    return *arg; 
} 

現在,當我只調用foo(ARG),拷貝構造函數當然是所謂的兩倍。當我僅僅打電話給酒吧(& arg)時,它只會被調用一次。因此,我期望

foo(bar(&arg)); 

複製構造函數在這裏被調用三次。但是,它仍然只被調用兩次。這是爲什麼?編譯器是否認識到另一個副本是不需要的?

在此先感謝!

回答

6

編譯器是否認識到另一個副本不需要?

確實如此。編譯器正在執行復制/移動省略。這是所謂的「as-if」規則的唯一例外,它允許編譯器(在某些情況下,如您的示例中的那樣)忽略對類的副本或移動構造函數的調用,即使它們有邊效果。

每一段的C++ 11標準的12.8/31:

當滿足特定條件時,一種實現被允許省略類 對象的複製/移動構造,即使爲複製/移動操作選擇的構造函數和/或對象 的析構函數具有副作用。在這種情況下,實現將被忽略的複製/移動操作的源和目標視爲簡單地引用同一對象的兩種不同方式,並且銷燬該對象 發生在兩個對象沒有優化就被摧毀了。 複製/移動操作的這個省音,稱爲複製省略,允許在下列情況下(這 可以合併,以消除多個副本):

- 在return聲明函數與類返回類型,當表達式是具有相同cv不合格 類型作爲函數返回類型的非易失性自動對象(不包括函數或catch-clause參數)的名稱時,複製/移動操作可以通過構造 自動對象直接進入函數的返回值

- [...]

- 當未綁定到引用(12.2)的臨時類對象將被複制/移動到具有相同cv不合格類型的類對象時,複製/移動操作可以通過 直接構建臨時對象到省略拷貝的目標可以省略/移動

- [...]

隨着GCC,你可以嘗試使用-fno-elide-constructor編譯標誌抑制這種優化並查看編譯器在沒有發生副本刪除時的行爲。

+0

非常感謝!幫助了我很多! – Veluria 2013-05-12 12:04:10

+0

@Pete:很高興:) – 2013-05-12 12:04:49

相關問題