2017-03-03 77 views
0

我試圖將一個十六進制編碼的字符串轉換成一個包含解碼字符串的const char *緩衝區。 爲此,我有一個函數(string hex_decode(string hex_input))接受字符串並對其進行解碼。
自行測試功能幾次後,我嘗試了以下調用:C++:嵌套時,兩個單獨的函數返回不同的結果嗎?

const char* hex_decoded_c_str = hex_decode(input).c_str(); 

,看到它返回完整的胡言亂語! 在努力調試問題,我把它分成兩個語句,就像這樣:

string hex_decoded_string = hex_decode(input); 
const char* hex_decoded_c_str = hex_decoded_string.c_str(); 

這一次,它完美地工作!
我很困惑,有沒有人知道可能會導致這樣的事情?

+0

@Biffen不再。 –

+0

我敢肯定,你在hex_decode中創建了一個本地字符串對象。由於string類具有深度複製賦值運算符,因此當您返回字符串時,它將被複制到hex_decoded_string對象中,而不會出現內存問題。在前一種情況下,您正在將hex_decoded_c_str指向堆棧內存,這是不正確的情況 –

回答

0

const char* hex_decoded_c_str = hex_decode(input).c_str(); 

你正在做一個參照string臨時對象(返回值),這是無效的內部表示,當hex_decode(input)超出範圍,則c_str()電話之後。

用另一種方法,您複製string對象,使該引用在您的範圍內有效。

+0

*「臨時對象[...],它在下一行中無效。」* - 這是不準確的。作爲評估包含創建點的完整表達式的最後一步,臨時對象被銷燬。如果在完整表達式後面的同一行上有代碼,則臨時文件已經在同一行上死了**。最好不要使用*「行」*的概念,這對C++編譯器來說是毫無意義的。 – IInspectable

+0

*「指令」*不是在C++中使用的術語。它通常歸因於彙編編程。仍然不準確是不準確的改進。 – IInspectable

+0

好的,目前的措辭對你更好嗎? –

-1

c_str()方法返回的指針在std::string實例被銷燬後變爲無效。

1

string hex_decode(string hex_input)返回臨時對象stringc_str()將一個指針返回到該字符串對象的私有部分。一旦臨時死亡(在完整表達式的末尾),該指針指向無法訪問的內存。這就是所謂的未定義的行爲

要解決此問題,請將返回值複製到本地string對象中,或者通過將其綁定到const string&引用來延長臨時對象的生存期。返回值c_str()的有效性與其被調用對象的生命週期相關。遵守不能由編譯器,庫或運行時強制執行。這是開發者需要確定的事情。

僅供參考,請參閱Lifetime

1

原型string hex_decode(string hex_input)表示一個新的字符串對象總是由hex_decode返回。標準的

段落12.2#3說:

臨時對象被銷燬作爲評價全表達式(詞法)包含了他們所創建點的最後一步。

此外c_str()返回一個指向內的字符串對象東西

當讀取文檔c_str()data()(現在執行同樣的功能),你可以推斷,從該線(見here21.4.7.1#1):

c_str() + i == &operator[](i)爲每i in [0, size()]

因此:

一旦c_str()結束還有;hex_decode()返回的臨時字符串必須被銷燬。在銷燬期間,它釋放底層字符數組。

但是,爲了保留字符數組,不需要複製臨時字符串。 12.2#4,5

有兩種情況,臨時狀態在與完整表達式結尾不同的點處銷燬。 ...第二個上下文是當引用綁定到臨時的時候。

所以你可以綁定一個常量引用到臨時對象,並節省拷貝構造函數調用:

const string & hex_decoded_string = hex_decode(input); 
const char* hex_decoded_c_str = hex_decoded_string.c_str();