[英]Is there a right way to return a new object instance by reference in C++?
所以我寫了一些代碼,我有這樣的事情:
class Box
{
private:
float x, y, w, h;
public:
//...
Rectangle & GetRect( void ) const
{
return Rectangle( x, y, w, h );
}
};
然后在一些代碼中:
Rectangle rect = theBox.GetRect();
哪個在我的調試版本中有效,但在發行版中有“問題”通過引用返回Rectangle - 我基本上得到了一個未初始化的矩形。 Rectangle類有一個=運算符和一個復制構造函數。 在沒有弄清楚為什么會破壞的情況下,我實際上更感興趣的是通過引用返回(新)對象的正確方法, 以便將復制分配給變量。 我只是傻嗎? 不應該這樣做嗎? 我知道我可以返回一個指針,然后取消引用,但我不願意。 我的某些部分感覺像按值返回會導致對象的冗余復制 - 編譯器是否會解決並優化它?
這似乎是一個微不足道的問題。 經過多年的C ++編碼后,我感到尷尬,我不知道這一點,所以希望有人可以為我清除這一點。 :)
您不能返回對堆棧上的臨時對象的引用。 你有三個選擇:
請注意,當您按照下面的代碼中的值返回時,編譯器應優化分配以避免復制 - 即,它將通過優化create + assign + copy到create中來創建單個Rectangle(rect)。 這僅在從函數返回時創建新對象時有效。
Rectangle GetRect( void ) const
{
return Rectangle( x, y, w, h );
}
Rectangle rect = theBox.GetRect();
不,你不能這樣做。 基本上,您在此示例中嘗試執行的操作是返回對堆棧上的臨時變量的引用。 返回引用時,它指向的變量將被銷毀,因此引用無效。
按值返回對象(參見下面的示例)實際上可能比您想象的要便宜。 編譯器通常會優化額外的副本。 這稱為返回值優化 。
Rectangle GetRect( void ) const
{
return Rectangle( x, y, w, h );
}
有沒有一種正確的方法通過C ++引用返回一個新的對象實例?
不,不是參考。 有兩種方法可以創建新對象:
在堆棧上:
Rectangle makeRect()
{
return Rectangle(x, y, w, h);
}
Rectangle r = makeRect(); // return by value
在堆上:
Rectangle * makeRect()
{
return new Rectangle(x, y, w, y);
}
Rectangle * r = makeRect(); // returned a pointer, don't forget to delete it later
為什么不這樣的?
class Box
{
private:
Rectangle mRectangle;
public:
Box(float x, float y, float w, float h) :
mRectangle(x, y, w, h) // Forgive me for making assumptions
// about the inner workings of your
// code here.
{
}
const Rectangle & GetRect() const
{
return mRectangle;
}
};
Rectangle rect = theBox.GetRect();
“任務”現在應該有效。 (從技術上講,這不是一個賦值運算符,而是一個被調用的復制構造函數。)
希望能幫到你
Box
類內部的引用(具有Rectangle
成員。建議返回const
引用)。 Rectangle
。 注意使用成語return SomeClass(a,b,c);
可能會在合適的編譯器上觸發返回值優化(RVO) 。 檢查std::complex
實現以獲取詳細信息。
你可能會對臨時生命的概念感到困惑。 考慮:
void f1( const A & a ) {
}
A f2() {
return A;
}
f1( f2() );
這是好的代碼,標准說f2創建的無名臨時必須掛起足夠長的時間才能在f1中使用。
但是,你的情況有所不同。 函數返回的東西是引用,因此無名臨時也是引用。 該引用必須掛起足夠長的時間才能有用,但它引用的內容不需要。
這是不可能的。 引用是指針的另一種形式,實際上您返回的對象的地址將被銷毀(析構函數被調用),甚至可能在調用者接收控件時被覆蓋。
你也可以
如果矩形按位看起來像Box,即包含四個浮點數(但有不同的成員函數),你可以使用reinterpret_cast ,雖然我根本不會推薦它:
const Rectangle & GetRect( void ) const
{
assert(sizeof(Rectangle) == sizeof(Box));
return reinterpret_cast <Rectangle> (*this);
}
我們可以使用auto_ptr,如果我們想使用新的和安全的內存泄漏
class Box {
private: float x, y, w, h;
public:
//...
std::auto_ptr<Rectangle> GetRect( void ) const
{
return std::auto_ptr<Rectangle> ( new Rectangle( x, y, w, h ));
}
};
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.