我們知道,string類為我們提供了很多的便利,我們用string類能方便的做字符串的各種操作,避免了我們直接操作char指針而產生的一些繁瑣的操作,和內存洩露的可能性,可是string類也是有陷阱的。下面我們看這樣一個例子,你能看出問題所在嗎?
*pc =<<pc<<
如果看不出來可以實際運行一下,會發現輸不出結果來,這是為什麼呢?
當我們寫getString函數時,如果其返回類型是const char*我們可能會分外小心,因為我們知道"just a test"生命會在函數返回後結束,我們可能會new一段空間來放這個字符串,然後返回指針,或者是要求調用者給一個空間來放這個字符串。但是當返回類型是string時,我們就不會如此小心翼翼,因為我們知道string類實現了拷貝構造函數和賦值函數。它會為我們操心空間分配和銷毀的問題。所以在這裡,我們直接返回"just a test"字符串是沒有問題的。
接著我們對一個string對象調用c_str函數貌似也沒有什麼問題,因為這是string類提供給我們的功能。但是這裡的關鍵是,我們沒有將getString()的結果賦給一個string對象就直接獲取其指針了,這時,系統並不會為string調用拷貝構造函數或是賦值函數,返回的string仍然只是一個臨時對象的狀態,它會在完成對pc的賦值後被銷毀,這時其內部的數據也不會存在了。
怎麼解決這個問題呢?
我們要改變c_str函數,讓它不要直接返回指針,而是new一段空間來放這個字符串再返回指針嗎?這樣,會降低效率,且每個調用c_str函數的用戶都需要操心delete指針的問題,很容易造成內存洩露。
我們要改寫getString函數,重新為返回的字符串new一段空間嗎?這麼做顯然也不合適。
這時,我們有兩種比較可行的解決方法。
1.不要直接返回臨時對象的指針,將臨時對象先賦值給一個局部對象,再獲取其指針。這樣,將上例改寫為
str = *pc =<<pc<<
2.如果要使用臨時對象的指針,將所有的使用放到一個語句裡進行。這樣,將上例改寫為
<<getString().c_str()<<
上面是個人愚見,歡迎大家討論!