2011-09-30 92 views
1

我目前有一個函數,是爲了返回T(模板函數)。所以我總是認爲它必須返回一個值,但是我最近偶然發現了一些東西。函數似乎不返回任何東西,當它應該

#define PRINTERROR(msg) \ 
std::cout << msg << "\n\tFILE: " << __FILE__ << "\n\tLINE: " << __LINE__ << "\n\tTIME: " << __TIME__ << std::endl << std::endl; 

這...

template<class T> 
T& Container_Vector<T>::GetFirstItem() 
{ 
    #ifdef CONTAINER_VECTOR_ERROR_CHECKING_ON 

    if (m_iCurrentSize > 0) 
    { 
     return m_pItems[0]; 
    } 
    else 
    { 
     PRINTERROR("ERROR: Attempting to retrieve item from an empty vector container"); 
    } 

    #else 

    return m_pItems[0]; 

    #endif 
} 

當我步執行代碼試圖測試如果MSG被輸出和錯誤檢查是在第一檢查(m_iCurrentSize> 0)失敗,則消息打印出來,然後它跳轉到函數「}」的末尾並且什麼也不返回?

通常我會得到一個編譯錯誤,說它必須返回一些東西。這裏發生了什麼,可以嗎?

雖然它實際上並沒有進入任何返回T的東西,但它確實返回了一些東西,但也可能是隨機存儲器地址。

回答

0

遺漏從函數返回值不幸的是不是一個編譯錯誤。

編譯器可以發出一個診斷消息(例如克++那樣如果與-Wall選項編譯),但它不是強制性的。

忽略返回的值是什麼,編譯器作者可以自由地假設一個程序員決不會做的,如果一個程序做它的標準指出,編譯器就可以忽略這個問題,無論發生什麼情況(未定義行爲) 。這總是程序員的錯。

在x86架構上通常是最終效果就是如果函數返回一個真正的「native」類型(例如,一個char或一個int),如果該函數是例如返回一個類實例(例如std::string),則可能會導致內存損壞或崩潰。但是請注意,對未定義行爲發生的情況的任何猜測都是......即純粹的推測,事實上對於C++語言規範而言可能會發生任何東西

0

這是未定義的行爲,如果CONTAINER_VECTOR_ERROR_CHECKING_ON被定義,並且!(m_iCurrentSize > 0)那麼你沒有迴應什麼。您可能會收到警告,但不會出現錯誤,因爲您確實有一個條件return。在這種情況下,該函數會返回垃圾,並且此後可能會損壞堆棧。

+0

好的。只是不知道在某些時候沒有返回的東西就可以編譯。堆棧可能因爲返回的內容而損壞,或者是幕後發生的其他問題導致問題? –

+0

@Ben Y:你正在調用未定義的行爲,所以會發生什麼......好吧,未定義!實際發生的事情取決於實現,調用約定等。堆棧**可能由於脫落返回某個東西的函數而被破壞,而實際上沒有返回任何東西。 –

3

您在#ifdef塊中的PRINTERROR之後缺少return。不這樣做會導致未定義的行爲。您必須在函數結尾處返回適當的值。

(這樣的邏輯錯誤可以在編譯時被捕獲與佔有設置標誌。例如,在G ++,你可以使用-Wall)。

1

首先,預處理採用的編譯之前的地方。爲了你的編譯器,代碼如下 -

如果CONTAINER_VECTOR_ERROR_CHECKING_ON定義:

template<class T> 
T& Container_Vector<T>::GetFirstItem() 
{ 
    if (m_iCurrentSize > 0) 
    { 
     return m_pItems[0]; 
    } 
    else 
    { 
     PRINTERROR("ERROR: Attempting to retrieve item from an empty vector container"); 
    } 
} 

如果CONTAINER_VECTOR_ERROR_CHECKING_ON沒有定義:

template<class T> 
T& Container_Vector<T>::GetFirstItem() 
{ 
    return m_pItems[0]; 
} 

你的第一種情況下不會對所有的支路的回報,你至少應該得到一個警告。 MSVS不報告編譯錯誤,但它確實會返回警告。你得到的隨機數就是函數退出之前返回寄存器中的最後一個值。