2015-07-22 58 views
0

存儲一個成員變量通過值:從const引用參數

class Test { 
private: 
    HugeObject h; // Copy 1 
public: 
    void SetObject(HugeObject hugeObject) { // Copy 2 
     h = hugeObject;      // Copy 3 
    } 
} 

// Somewhere else 
Test t(); 
t.SetObject(HugeObject()); 

這是不好的,因爲創建三個隱式拷貝。如果我將SetObject()的參數更改爲const HugeObject& hugeObject,這也是不好的,因爲我將存儲不再存在於該函數範圍之外的內容。

因此,防止兩次複製和存儲無效數據,我可以複製,而不是僅僅兩次:

void SetObject(const HugeObject& hugeObject) { 
    h = HugeObject(hugeObject); // Copy constructor 
} 

這是處理這種情況還是我誤解的東西有效的方法是什麼?愚蠢的優化或者根本不是優化?除了存儲指針之外,還有更好的方法嗎?

+0

閱讀移動構造函數[這裏](https://msdn.microsoft.com/en-us/library/dd293665.aspx) – ChajusSaib

回答

1

當你聲明h班上第一,你實際上做的是調用對象的默認構造函數,這是隱含呼籲創建不使用顯式語法的對象;也就是

HugeObject h; // Calls default constructor implicitly. 
HugeObject h2 = HugeObject(); // Still calls default constructor. 
HugeObject ougeHobject = HugeObject(h); // Calls copy constructor. 
h2 = ougeHobject; // calls HugeObject's operator= 

最後一部分是我真正想到的。當您將h指定爲hugeObject時,您實際上使用HugeObjectoperator=。這是而不是與施工相同。如果operator=未由類定義,則C++實現將其合成;此默認工作方式是將基本類型的右側對象(例如,double)的每個成員分配給左側對象上的相應成員。對於存儲爲變量hugeObject,的類類型,將調用其相應的operator=

直接現在要回答這個問題,如果你想限制你做的份,只是分配小時,在SetObject一個的hugeObject參考,因爲這兩個已經被實例化:

void SetObject(const HugeObject& hugeObject) { 
    h = hugeObject; 
} 

雖然技術上超出範圍,const HugeObject&的值通過HugeObjectoperator=複製到h。這不會隱含地構造一個新的對象,因爲兩者都已經被實例化;再次,它只需撥打operator=

+0

謝謝,這個和其他答案讓我意識到我所做的誤解。可以肯定的是:分配一個const引用是一種有效的做法,還是一種hacky? – idlackage

+0

@idlackage,我沒有看到爲什麼分配給一個const引用會是hacky。它本質上只是複製數據。 – settwi

1

這是不好的,因爲創建了三個隱式副本。

實際上,在這種情況下只發生一個副本。臨時HugeObject()臨時構建爲參數hugeObject,然後從那裏複製到h

如果我將SetObject()的參數更改爲const HugeObject& hugeObject,那也不好,因爲我將存儲的東西將不再存在於該函數的作用域之外。

這也不準確 - 你仍然複製到h,你不存儲對它的引用。這將節省您的副本中的情況:

HugeObject h; 
t.SetObject(h); // copy from h into t.h, no copy necessary 
       // into the argument of SetObject() 

hugeObject通過const&是做它在C++ 03的最佳途徑。如果你有機會到C++編譯器11,和你HugeObject是有效的活動,你應該還添加一個右值過載:

void setObject(HugeObject&& hugeObject) { 
    h = std::move(hugeObject); 
} 
1

爲什麼不給施工期間的對象?然後你得到原創和複製。

#include <iostream> 

using std::cout; 

class Huge 
{ 
public: 
    Huge() { cout << "constructor\n"; } 
    Huge(const Huge & h) { cout << "copy\n"; } 
    Huge & operator = (const Huge & h) { cout << "assignment\n"; return *this; } 
}; 

class Holder 
{ 
    Huge h; 
public: 
    Holder(const Huge & h_) : h(h_) {}; 
}; 

int main() 
{ 
    Huge bar; 
    Holder foo(bar); 
} 

輸出:

constructor 
copy 

Live Example