2012-11-20 22 views
2

如果我有以下代碼:這個字符串的範圍是什麼?

{ 
    UnicodeString sFish = L"FISH"; 
    char *szFish = AnsiString(sFish).c_str(); 

    CallFunc(szFish); 
} 

那麼什麼是所創建的臨時AnsiString類型的範圍,多長時間是szFish指向有效的數據嗎?對於CallFunc函數它仍然有效嗎?

它的範圍是持續一行還是整行?

+0

不熟悉'UnicodeString'或'AnsiString',但字符串必須至少持續到塊結束。 –

回答

2

的C++標準的11 $ 12.2.3說:

當實現引進了類的臨時對象, 具有非簡單的構造函數(12.1,12.8),它應確保爲臨時對象調用構造函數 。類似地,應該調用析構函數臨時使用一個不重要的析構函數(12.4)。 臨時對象被作爲 中最後一步評估完整表達式(1.9)(詞法上)包含創建它們的地點的最後一步而被銷燬。即使評估 以拋出異常結束,情況也是如此。破壞臨時對象的值計算和副作用僅與 完整表達式關聯,而不與任何特定的子表達式關聯。

(重點煤礦)

還有其他注意事項這一點,但他們並不在這種情況下適用。在你的情況下,充分表達這句話的指定部分:

char *szFish = AnsiString(sFish).c_str(); 
//    ^^^^^^^^^^^^^^^^^^^^^^^^^ 

因此,即時szFish分配,你的臨時對象的析構函數(即AnsiString(sFish))將被調用並且其內部存儲器表示(其中c_str()指向)將被釋放。因此,szFish將立即成爲懸掛指針,任何訪問都將失敗。

您可以通過說出

CallFunc(AnsiString(sFish).c_str()); 

相反,這裏解決這個問題,臨時將(再次)的表達後破壞(即,就在;)和CallFunc會能夠讀取原始字符串。

5

szFish是調用CallFunc()之前無效的,因爲AnsiString是立即破壞和szFish指向這將剛纔被刪除其內部緩衝區臨時對象。

確保AnsiString實例對調用CallFunc()有效。例如:

CallFunc(AnsiString(sFish).c_str()); 
4

我將取代:

char *szFish = AnsiString(sFish).c_str(); 

有:

AnsiString as(sFish); 
char *szFish = as.c_str(); 

我不知道AnsiString類,但在你的代碼的析構函數將您的來電之前進行發射CallFunc(),並且很可能會釋放您指向*szFish的字符串。當您用堆棧上的「named」對象替換臨時對象時,其生存期將延長至定義塊的末尾。

+0

是的,我已經修復它。我想100%確定爲什麼。 – Bagpuss

+0

這是一個很好的解釋(取自C++標準,我相信)一個臨時對象的生命週期http://stackoverflow.com/questions/4214153/lifetime-of-temporaries $ 12.2/3-「臨時對象被銷燬作爲最後一個步驟評估完整表達式(1.9)(詞彙)包含它們創建的點,即使評估結束於拋出異常也是如此。「 – piokuc

1

AnsiString的範圍在此情況下爲「從調用前的c_str( ),直到之後。「它可以幫助這樣設想一下:

char *szFish; 

{ 
    AnsiString tmpString(sFish); 
    szFish = tmpString.c_str(); 
}