C++中string轉換爲char*類型返回後亂碼問題

問題來源:數組

  在寫二叉樹序列化與反序列化時發現序列化函數爲char* Serialize1(TreeNode *root)  其函數返回類型爲char*,可是我在實現的過程當中爲了更方便的操做添加字符串使用的是C++中string類型的變量,這就致使我最後獲得的結果res是string類型,如果要返回須要轉化爲char *類型。而等我將string類型轉爲char*後返回在主函數中就成了亂碼。數據結構

 

先直接說最後的解決辦法:函數

  第一種:定義一個char數組,數組長度爲stringlength+1,將string的內容依次賦值給char數組,最後加上'\0' ,而後返回char數組名就好了。測試

  第二種:將string定義爲類的成員變量spa

  就貼第一種方法的代碼3d

char *result = new char[res.length() + 1];  //定義須要返回的result對象
for (int i = 0; i < res.length(); ++i)
{
     result[i] = res[i];    //將string類型的res內容都放到result內
}
result[res.length()] = '\0';  //加上結束符\0

 

再說說我嘗試的方法指針

嘗試1:調試

  一開始我是直接定義char *result=&res[0];想要經過這個語句直接返回這個string類型變量的首地址,可是失敗了,在主函數中的結果變量是亂碼 "葺葺葺葺葺葺葺葺葺葺"code

嘗試2:對象

  因而我開始思考可能的緣由  

  1.考慮到局部變量可能隨着函數釋放,所以致使我返回的指針指向的內容隨着函數一塊兒釋放致使了亂碼,但一想到平時寫的函數都是正常返回的,因此這個我很快否決了,但最後發現這個思路是對的。至於日常寫的函數都是正常返回則是由於沒有涉及到類型轉換。  

  2.經過VS的調試發現我使用的char *result=&res[0]語句返回的是res的首個元素地址,並非res的首地址,由於string做爲std封裝的數據結構除了char*這種從C吸取過來的結構還有內存分配allocate這些東西因此致使其內存地址並不像char數組那樣是首個元素地址

  因此我想幹脆把整個string類型的res都賦值給char *類型的result

  因此我嘗試了char *result=(char*)res.data();語句,將res(res是string類型的結果)賦給result,轉換是成功的,但返回值依舊失效(且這種轉換須要本身加上\0結束符)

  而後嘗試char *result=(char*)res.c_str(); 結果也是成功的,但返回值依舊失效。

  最後嘗試,用new新建一個char數組,將res的內容所有拷貝到char數組內,而後將數組名返回,終於成功。

 

問題根源

  經過VS調試我最終發現了問題根源所在:res所佔內存隨着函數結束而被釋放

  這是函數未執行完的調試界面

  這是執行完調試界面

 

   很明顯:res沒有了,在函數執行完畢後res內存也跟着被釋放了而char數組result卻仍然存在。他們的不一樣點在哪:result是返回值 

  咱們知道函數的函數棧知識點,棧內存放着函數入口地址,局部變量,返回地址等,我猜想result做爲要被返回的對象其內存空間應該是不隨着函數一塊兒被釋放的,也就是主函數內的返回值應該仍是用那塊內存,通過測試這個結論是對的。主函數中的變量的確是使用返回值那塊內存。

  到這裏就發現了,雖然執行char* result=(char*)res.c_str()語句能讓result內是完整的結果內容(也就是轉換完成),但result會隨着string類型的res的釋放而致使char*類型的result所指向的內存空間內容所有清空。最後雖然返回了result所指的空間但裏面的內容早就被清空了。就比如把內存比做一塊地,res先在其上面蓋了一座房子,而使用上面轉換語句後result也是房子的主人,這下房子有了兩個主人,他們都能對房子進行操做。正由於他們都能進行操做,當他們所屬函數結束也就是res大限到來之時,res將本身創建的房子銷燬了。那麼result也就沒有房子可住了。也就是他們公用的那片內存被初始化,這時主函數雖然收到了返回地址但那片地址已經沒有內容了。也就致使亂碼了。

  到這裏,問題的根源就知道了,那麼解決方法也就很明顯了:1.內存分離,將res和result的所屬內存地址分開。2.或者想辦法讓res所在內存不隨着函數結束而釋放.

  具體實現:

  第1種.上面那段new新建char*變量的代碼。爲result從新開闢一段空間。

  第2種.i:若在類裏:將res設爲類的成員變量或者static成員變量(最好不要,能成功但會有新問題出現),他們都不會隨着成員函數的結束而釋放。區別就是普通成員變量會隨着對象的釋放而釋放,static不會,它是存放在靜態存儲區

      ii:如果像C這類面向過程代碼就是將res設爲全局變量便可

相關文章
相關標籤/搜索