2012-11-14 62 views
0

我有一個情況我有以下簡要:在C++中臨時克隆?

class K { 
    K clone() const{K cl; /* clone this to cl then */ return cl; } 
}; 
K* call_clone() 
{ 
    K k; 
    return new K(k.clone()); 
} 

編譯器的優化後,將在本倍加複製?

或者:
會更有效的執行C*clone()

像這樣:

class K { 
    K* clone() const { K*p=new K(); /* clone this to *p then */ return p; } 
}; 
K* call_clone() 
{ 
    K k; 
    return k.clone(); 
} 

(我問這個,因爲即使K的淺拷貝可能是昂貴的,這將是在實踐中的一類數據結構)

+2

我認爲你需要閱讀一些關於C++ *複製構造函數*,也可能*參考文獻* – Roddy

+0

@羅迪:對於第二種情況 - 不一定。在使用多態性時,像他的第二個例子中的clone()可能是必需的。你可以在Java,C#等語言中看到所有類型的東西。 – 2012-11-14 14:08:52

回答

0

編譯優化後,這會被雙倍複製嗎?

它取決於編譯器。任何現代編譯器都不會執行雙重複制,這稱爲Return Value Optimization。它不取決於clone()的定義是否可用。

C * clone()會更有效嗎?

不,它不會。動態內存管理(操作員新增/刪除等)非常昂貴。它可能比執行雙重副本更爲昂貴,具體取決於您的副本構造函數實際執行的操作。

+0

請注意,RVO有點脆弱,所以您需要了解編譯器如何/何時優化它。然而,'move'-return非常強大:如果你返回一個局部變量,編譯器可以(通常是)'移動'。實現一個快速的'K(K &&)'移動構造函數,'call_clone'將最多調用2次移動。 'pImpl'模式可以幫助你快速移動構造函數,而其他時間則需要花費一些開銷。你可能想知道你的'K'複製/移動的語義,並確保它們簡單易懂...'K clone()'應該是一個拷貝構造函數,不應該嗎? – Yakk

+1

使用'C * clone()'而不是'C clone()'的原因與優化無關。如果您只想在編譯時複製類型已知的對象,則可以直接使用複製構造函數。除非需要動態分派,否則不使用函數clone。這幾乎意味着返回一個指針。 –

+0

@JamesKanze:是的。如果碰巧有一個沒有RVO的編譯器,並且複製兩次比調用'new'並複製一次更昂貴,那麼使用'clone()'會更好。但現在很難想象這種情景IRL。 – 2012-11-14 15:06:51

0

傳統clone()上創建一個副本堆,例如:

T* clone() { return new T(*this); } 

否則,人們可以簡單地調用複製構造函數。

所以,call_clone()應該是這個樣子:

K* call_clone() { 
    K k; 
    return k.clone(); 
} 
編譯器優化後

,這會倍加複製?

如果clone()定義可用(該函數是內聯的或由模板生成的),編譯器可以優化創建局部變量並進行復制。

+1

C++中是否存在「傳統克隆」這樣的東西? – Roddy

+0

好吧,OpenCV'cv :: Mat'有'cv :: Mat clone()const;' –

+0

@Roddy:是的,沒有。已經有數不清的嘗試來標準化一個擁有深度拷貝的智能指針,通常被稱爲'value_ptr',而大的障礙一直是一個聲稱的clone()函數的性質。 –