2013-06-21 109 views
3

我的程序中有一個特定的類,我用它來繪製各種形狀並將事件添加到形狀中。從方法中返回一個指針

vector<XQuad*> _inputMappedShape; 
void addRegularShape(Container inputPoints, Container outputPoints){ 
XQuad quad; 
setInputPoints(quad, somePoints); 
setInputPoints(quad, somePoints); 
setArrowHandles(quad, somePoints); 
_inputMappedShape[currentIndex++] = &quad; 
} 

XQuad* getMappedShape(int index){ 
return _inputMappedShape[index]; 
} 

void setInputPoints(XQuad& quad, Point* somePoints); 
void setOutputPoints(XQuad& quad, Point* somePoint); 
void setArrowHandles(XQuad& quad, Point* somePoint); 

請注意,在上面的代碼(在方法addRegularshape),我通過參考其他方法使quad將它添加到vector收集之前。

在我的主程序中,我試圖找回使用getMappedShape方法,會返回一個指向四我的目的的形狀。
XQuad* returnedShape = getMappedShape(0)

我檢查的quad的存儲器地址在addRegularShape方法分配和由指針(來自方法getMappedShape)正在返回的地址和存儲器地址是相同的。
但是,不知何故我XQuad類中的數據從所述getMappedShape返回時是不正確的(即,不將其在XQuad參考對象修改在其他三個成員函數的一個),並代替了一些無用值。我無法找到爲什麼發生這種情況的原因,並懷疑內存被損壞或出現問題,我將addRegularShape中的引用對象更改爲指針,如下所示。
XQuad* quad = new XQuad();

在此之後,程序開始返回正確的值,但我仍然對它爲什麼會發生這種情況有點懷疑?是不是將XQuad對象添加到集合中的正確方式?或者在這裏存在一些範圍問題,即當方法超出範圍時,對象被銷燬,我從集合中實際返回的東西現在變成了垃圾值?

回答

2

您在返回本地對象(這將在函數調用結束時銷燬)的地址,所以你最終未定義行爲。

+0

有沒有這種情況,我實際上可以從方法返回參考?我試圖使用引用來避免顯式使用指針。例如:一個可能具有用構造函數初始化的私有變量的類。該類的getter方法返回一個對私有變量的引用,例如'int&getTopLeftCornerX(return _pTopLeftX);'其中_pTopLeftX是該類的私有變量,並且用類構造函數初始化。 – user1240679

+0

給OP一個很好但也有點痛苦的提示:提高編譯器的警告級別。嘗試編寫完全不產生警告的代碼。例如,gcc會警告你關於返回一個局部變量的引用。 – arne

+0

@ user1240679:有很多情況。例如。 (std :: vector :: at()'做。 Çlass方法通常可以返回對類數據成員的引用;他們確實超過了一個電話。但你的情況是一個典型的例子,你不應該這樣做。 Getters應該是'const',最好返回一個普通的'int'。 – MSalters

3
_inputMappedShape[currentIndex++] = &quad; 

意味着您正在將四個地址分配給_inputMappedShape。所以你會在你的完整程序中得到這個地址..但是在函數的結尾,與quad對象相關的addRegularShape(...)數據將被破壞,因爲它的作用域將會被覆蓋。並且_inputMappedShape將保留四個地址沒有數據。

+0

如果相應的指針指向被銷燬的對象,則引用將引用被銷燬的對象。所以原則上你可以返回一個對象的引用,如果你可以返回一個指向該對象的指針。在實踐中,如果該對象必須被調用者刪除,您將希望返回一個指針(或更好的智能指針)到一個對象。 – celtschk

3

你已收到垃圾值,因爲我們通過本地對象XQuad的地址成員變量_inputMappedShape [CURRENTINDEX ++] = &四

永遠記住這個當你創建一個局部變量,然後分配給本地變量的內存總是棧。所以只要你離開函數堆棧展開,現在你的_inputMappedShape [currentIndex ++]將指向一些實際上不存在的位置。

但是,如果您在方法內部使用新運算符創建變量,則分配給它的內存將不再堆棧,而是堆上。在這種情況下,從該函數返回時,堆棧展開將不會影響變量_inputMappedShape [currentIndex ++]