2014-10-01 38 views
0

我有一個非常簡單的代碼片段:COUT的char *是不同

#include <iostream> 

using namespace std; 

string getString() { 
    return "test"; 
} 

int main(){ 
    const char* testString = getString().c_str(); 
    cout << "string 1:" << testString << endl; 
    string dummy[] = {"1","2","0"}; 
    cout << "string 2:" << testString << endl; 
    return 0; 
} 

我想到兩人COUTS將打印相同的輸出,但我得到的輸出是

string 1:test 
string 2:1 

任何人都可以解釋爲什麼會發生這種情況?另外,我觀察到兩件事:

1)如果dummy[]int類型,那麼它們將打印出與預期完全相同的字符串test

2)如果我首先將getString()分配給一個字符串變量,那麼將第一行改爲const char* testString = variable.c_str();,然後它們會按照預期輸出相同的字符串。

回答

4

行爲未定義。

const char* testString = getString().c_str(); 

getString返回一個臨時對象,當評估完成時它將被銷燬。作爲結果。 testString指向被破壞對象的內部,導致未定義的行爲。

實際上,可能會發生數據仍然在該地址一段時間,這就是爲什麼第一個cout給出錯誤的正確性。

+0

true,沒有進行內存分配來返回字符串。 – Elod 2014-10-01 16:40:17

+0

@Elod:內存分配給臨時;但是暫時的,它在這條線的末尾被摧毀了。 – 2014-10-01 16:42:16

1

您可以設置指針,指向該聲明

const char* testString = getString().c_str(); 

所以該方案已不確定的行爲後刪除臨時對象。

正確的代碼可能看起來像

const char * getString() { 
    return "test"; 
} 

int main(){ 
    const char* testString = getString(); 
//... 

,因爲字面字符串具有靜態存儲持續時間。

+0

修復了這個簡單的例子;但是當你需要返回一個'string'時並沒有幫助。 – 2014-10-01 16:45:45

+0

@Mike Seymour這是另一個問題。你可以自己問問。 – 2014-10-01 16:47:34

0

當您從管理該字符串的內存的字符串對象中獲取低級別字符指針時,該指針僅適用於對象處於活動狀態的特定

實際上它比這更窄。如果您在字符串對象上調用任何非const成員,這意味着即使對象析構函數未運行,也不能相信您從之前調用c_str()的任何值仍然很好。

#include <iostream> 

using namespace std; 

string getString() { 
    return "test"; 
} 

int main(){ 
    string testString = getString(); 
    const char * testCstring = testString.c_str(); 
    cout << "string 1:" << testCstring << endl; 
    string dummy[] = {"1","2","0"}; 
    cout << "string 2:" << testCString << endl; 
    return 0; 
} 

這是合法的,但不從c_str()所做的任何修改改變你 - 或有被摧毀該字符串得到它後的字符串依靠指針。

另外請注意,沒有必要從字符串中獲取char *以輸出它。開始思考使用字符串對象,不要去char *,除非你有充分的理由。

相關問題