2011-04-05 97 views
0
CARD& STACK::peek() 
{ 
    if(cards.size == 0) 
    { 
     CARD temp = CARD {-1, -1}; 
     return temp; 
    } 
    return cards.back(); 
} 

這是我遇到麻煩的功能。STACK.peek功能,遇到一些麻煩,C++

  • CARD只是一個struct有兩個int變量,稱爲ranksuit

  • STACK是管理std::vector<CARD>class,即cards

功能應該一個reference返回到卡上的堆棧的頂部,或者所述參考返回到虛擬卡若vector是空的。

首先,我收到一條警告,說明返回了對局部變量temp的引用。那有什麼問題?這將如何影響功能?我該怎麼做呢?

其次,我想使用此功能與其他功能我創建了名爲cardToString

char* cardToString(CARD& c); 

它應該使用ranksuit變量傳遞CARD查找表中的字符串值,將兩個字符串連接在一起,並返回一個指向新字符串的指針。

所以最終的結果是這樣的:

cout<<cardToString(deck.peek())<<"\n"; 

,但此行的代碼將執行到cardToString功能,然後就停止出於某種原因。這讓我非常惱火,因爲它只是停下來,沒有錯誤信息,而且看起來不像我有什麼不妥。

有人可以幫我嗎?

編輯:這裏是cardToString功能

char *cardToString(const CARD& c) 
{ 
    if(c.r >= 13 || c.r < 0 || c.s >= 4 || c.s < 0) 
    { 
     std::cout<<"returned null"; 
     return NULL; 
    } 

    char *buffer = new char[32]; 

    strcpy(buffer, RANKS[c.r]); 
    strcat(buffer, " of "); 
    return strcat(buffer, SUITS[c.s]); 
} 

我特別想要的功能STACK.peek()返回已經存在的STACK頂部CARD的地址。這樣做似乎更有意義,而不是創建我想要返回的卡的副本。

+0

發佈'cardToString'函數可能有助於診斷問題。 – uesp 2011-04-05 23:59:36

+1

按指針返回的值與參考值的比較應該是*語義*的決定。在語義上,通過引用返回沒有任何意義,因爲可能的返回值之一是,如您標記的那樣,是暫時的。 – ildjarn 2011-04-06 00:15:01

+0

@ildjam該類可能包含一個虛擬的'CARD',它返回一個引用(類似於'std :: string :: npos')。 – user470379 2011-04-06 00:58:18

回答

1

您不能返回對局部變量的引用,因爲函數返回時局部變量不再存在。

您需要按值返回,而不是通過引用(即CARD STACK::peek() { ... })。

+0

'cardToString'需要一個'CARD const&'而不是'CARD&',否則'cardToString(deck.peek())'將不起作用,因爲'deck.peek()'將返回一個右值。 – ildjarn 2011-04-05 23:59:15

3

首先,我得到一個警告,指出返回了對局部變量temp的引用。那有什麼問題?這將如何影響功能?我該怎麼做呢?

正如其名稱所暗示的,局部變量對於它所屬的函數是局部的,所以它在函數返回時被銷燬;如果您嘗試返回對其的引用,那麼您將返回對該函數返回時不再存在的內容的引用。

雖然在某些情況下這看起來可能工作,但你只是幸運因爲堆棧沒有被覆蓋,只是調用其他函數,你會發現它會停止工作。

您有兩種選擇:首先,您可以通過值而不是引用返回CARD;然而,這具有不允許呼叫者使用該參考來修改存儲在vector中的該參考(這可能或可能不是期望的)的缺點。

另一種方法是具有存儲在STACK類的靜態虛擬CARD情況下,將不會有這些生命週期問題,可以返回時,你不必在vector元素;然而,你應該找到一種方法來「保護」它的領域,否則一個「愚蠢的」調用者可能會改變你的「單身」虛擬元素的值,從而搞砸了這個類的邏輯。一種可能性是CARDclass中將封裝其字段,並且如果它是虛擬元素將拒絕對它們的寫入訪問。

至於cardToString函數,你可能在字符串上做錯了什麼(而且我幾乎可以肯定你也試圖在本例中返回一個本地),但是沒有看到它的函數體很難說什麼。

順便說一句,以避免許多問題串,我建議你使用,而不是char *std::string類,這需要最醜陋的和通常char *低級別的內存管理的路程。

此外,我建議你改變cardToString採取const參考,因爲很可能它不需要改變作爲參考傳遞的對象,並且清楚標記這個事實是很好的做法(編譯器會警告你如果你試圖改變這樣的參考)。


編輯cardToString功能應該是做工精細,只要RANKSSUITS陣列都OK。 但是,如果您使用的是類似於您寫的功能,則表明您正在泄漏內存,因爲對cardToString的每次調用,您都會使用new進行分配,該分配永遠不會與delete一起釋放;因此,每次調用都會丟失32個字節的內存。

如前所述,我的建議是隻使用std::string並忘記這些問題;你的功能變得如此簡單:

std::string cardToString(const CARD& c) 
{ 
    if(c.r >= 13 || c.r < 0 || c.s >= 4 || c.s < 0) 
     return "(invalid card)"; 

    return std::string(RANKS[c.r]) + " of " + SUITS[c.s]; 
} 

而且你不必擔心內存泄漏和內存分配了。


對於參考/值的事情:如果調用者不需要使用參考修改存儲在矢量對象,我強烈建議按值傳遞。性能影響可以忽略不計:兩個int而不是一個指針意味着在大多數32位體系結構中8個字節與4個字節,而在大多數64位機器上8個字節與8個字節(並且通過指針訪問字段的代價很小)。

這種微型優化應該是您最後關心的問題。你的首要任務是編寫正確的工作的代碼,你應該做的最後一件事是讓微優化克服這個目的。

然後,如果您遇到性能問題,您將分析您的應用程序,找出瓶頸位置並優化這些關鍵點。

+0

感謝關於內存泄漏的提示,請牢記這一點。我只會使用你建議的字符串,但我試圖學習如何做很長的路。 – Morshu 2011-04-06 00:30:06

+0

@Morshu:C++的方式是'std :: string';將'char *'和完全手動的堆管理留給C程序員。 – 2011-04-06 00:32:12

+0

好escuuuse我大聲笑即時通訊只是開玩笑感謝您的幫助,雖然 – Morshu 2011-04-06 01:18:39