2012-10-31 39 views
3

GetTypeName是的std :: string,下面的代碼奇怪常量字符*行爲

printf("%#x\n", proto->GetTypeName().c_str()); 
printf("%s\n", proto->GetTypeName().c_str()); 
const char *res = proto->GetTypeName().c_str(); 
printf("%#x\n",res); 
printf("%s\n",res); 

產生這樣的輸出:

0x90ef78 
ValidTypeName 
0x90ef78 
ю■ю■ю■ю■ю■ю■ю■ю■ю■ю■ю■ю■ю■ю■ю■ю■ю■ю■ю■ю■ю■ю■ю■ю■ю■ю■ю■ю■←ЬЬQщZ 

地址總是相同;下面的代碼(行是交換)

const char *res = proto->GetTypeName().c_str(); 
printf("%#x\n",res); 
printf("%s\n",res); 
printf("%#x\n", proto->GetTypeName().c_str()); 
printf("%s\n", proto->GetTypeName().c_str()); 

產生這樣的輸出,地址總是一樣:

0x57ef78 
 Y 
0x580850 
ValidTypeName 

我在做什麼錯?

strlen(res) 

返回無效的大小,所以我甚至不能strcpy。

回答

5

YourGetTypeName函數返回一個std :: string,並且您正在調用c_str來獲取指向該字符串中內部數據的指針。

由於這是返回一個臨時的的std :: string將在聲明

const char *res = proto->GetTypeName().c_str(); 

結束時刪除,但你仍然有指向現在已刪除的數據資源。

編輯:改變你的代碼是這樣的: -

const std::string& res = proto->GetTypeName(); 

,並在這樣的printf的該字符串調用.c_str(): -

printf("%#x\n",res.c_str()); 
printf("%s\n",res.c_str()); 

分配一個臨時的參考將臨時的生命週期延長到與參考的壽命相同...

更好的是,只需使用std :: string和iostream進行打印並停止使用低電平當不必要的指針:)

+0

不會返回一個const std :: string&work? – amaurea

+1

@amaurea:可能,但它有一個缺點:http://stackoverflow.com/a/134777/166749 –

+0

使用移動語義,爲什麼不把返回的字符串存儲在實際的字符串中?然後有人看着代碼就不必知道GetTypeName的簽名來驗證字符串的生命週期...... – Yakk