2011-02-01 122 views
1

我想在兩個類之間進行轉換並避免臨時對象。如何避免轉換函數中的複製構造函數?

這裏是我的Square聲明:

class CSquare 
{ 
public: 
    int dimension; 
    CSquare(int dimension); 

    // Conversion to Rectangle 
    operator CRectangle(); 

    ~CSquare(void); 
}; 

,這裏是我的Rectangle聲明:

class CRectangle 
{ 
public: 
    int length; 
    int width; 

    CRectangle(int length, int width); 

    //Copy Constructor 
    CRectangle(const CRectangle& anotherRectangle); 

    ~CRectangle(void); 
}; 

爲什麼

CSquare aSquare = CSquare(10); 
    CRectangle convertedRect = (CRectangle) aSquare; 

調用拷貝構造函數?

我有一個轉換功能:

CSquare::operator CRectangle(){ 
    return CRectangle(CSquare::dimension,CSquare::dimension); 
} 

但我仍然得到一個臨時對象。

如何避免臨時對象?

+0

我忘了稱讚你不必矩形從廣場或周圍的其他方法:) – 2011-02-01 18:46:13

回答

1

如何避免臨時對象?

你不知道。這就是轉換的工作原理。暫時可能會被刪除(直接構建到目的地),但這不是必需的。

這聽起來像你想移動語義,這是在C++ 0x。即使那樣,臨時的「存在」,但它可以被移動而不是被複制,對於那些重要的類型來說,它通常更加高效。

這個正方形/長方形的情況不是真的你關心的情況,只用於這裏的一個例子嗎?

2

因爲您正在複製矩形。

我真的不知道還能說什麼。在你展示的情況下,編譯器可以自由地優化掉電話,但他們不需要。顯然你的不是。

編輯....

至於如何避免它,你真的不能。你可以嘗試調整優化,但是要想看看你是否成功了,尤其是在這樣一個小的,微不足道的構造中,是非常困難的。如果我在哪裏,我不會那麼擔心,除非我真的通過分析我的代碼發現,在這個功能上花費了過多的時間。然後,我會尋找方法來使用代碼來減少算法以減少副本。

+0

我不知道的Visual C++是否在調試模式優化實際上獲得。 – 2011-02-01 16:40:56

0

正在創建一個臨時CRectangle對象,然後將其複製到convertedRect。

+0

在標準C++中不可能。 – UncleBens 2011-02-01 16:56:01

+0

@UncleBens - 什麼?什麼是不可能的? – 2011-02-01 17:00:18

0

我假設自operator CRectangle返回CRectangle的實例,將調用複製構造函數以獲取返回值。

+0

否。構造函數在使用初始化語法在本地對象中創建該返回的副本時被調用。 – 2011-02-01 16:40:43

0

通常這取決於編譯器。 返回值優化由大多數編譯器完成。因此,不是創建一個臨時對象並將其分配給您的對象,而是調用對象中的Ctor副本。

而且這裏看看Copy constructor vs. return value optimization

5

您可以通過在CRectangle的編寫轉換構造避免拷貝構造:

CRectangle::CRectangle(const CSquare & sq) 
    :length(sq.dimension), 
    width(sq.dimension) 
{} 
... 
... 
CSquare aSquare(10); 
CRectangle convertedRect(aSquare); 
0

我不能說出你說的哪種類型的對象有暫時的。

如果正方形,那麼你需要刪除任何藉口編譯器創建一個:

CSquare aSquare(10); 

如果矩形,然後你shoudl使用,而不是操作者的轉換構造,通過@PigBen的建議:

Rectangle::CRectangle(const CSquare & sq) 
    :length(sq.dimension), 
    width(sq.dimension) 
{} 
// And then: 
CRectangle convertedRect(aSquare); 
0

在這種特殊情況下,您可以通過不具有轉換功能來代替繼承。例如: -

class CRectangle 
{ 
public: 
    int length; 
    int width; 

    CRectangle(int length, int width); 
}; 

class CSquare : public CRectangle 
{ 
public: 
    CSquare(int dimension) : length(dimension), width(dimension) 
    {} 
};