看板 C_and_CPP 關於我們 聯絡資訊
※ 引述《descent (「雄辯是銀,沉默是金」)》之銘言: : ※ 引述《KaryuuIssen (一閃)》之銘言: : 這個 tmp_x 就不存在了。 : 所以你的指標 x 指向一個已經不存在的 tmp_x, : 自然是任何事情都有可能發生了。 : : const char* y = string("222").c_str(); : : cout << x << "\n"; // 222(第一行不註解的話會是111) : : cout << y << "\n"; // 222 : : } : : 上面程式碼x和y的輸出都是222 這種錯誤還有另外一種很常見的形式,常見於下面這樣: class Foo { const char* literal; void setString(const char* a); }; void foo::setString(const char* a) { literal = a; } void foo::print() { //作者既然那麼傳統的用const char*,會用傳統的printf也很合邏輯 std::printf("%s", a); } ------- foo.setString(string("This is a pen!").c_str()); foo.print()//炸掉,原因同上篇 ------- const char* a = "This is a pen!"; foo.setString(a); foo.print();//不會炸掉,大概也是大家預期的呼叫方法 即使出了a的scope仍然不會炸掉,因為a會寫在.data裡面 ------- string a = "This is a pen!"; foo(a.c_str()); foo.print()//這個最慘,當下不會炸,出了a的scope就會死,很難debug! //這樣會炸鍋而且炸得很多人不明不白 ------- 這其實牽扯到一個STL設計上的FAQ,為什麼string::c_str()不設計成隱式轉型 讓他可以直接像這樣,用起來方便很多 : string a = "Pineapple!"; foo(a); //string有實作operator const char*()就可以讓他隱式轉型 我想大家應該就知道為什麼了.... 更不用講當string做字串更改,都有機會c_str()變成另外一個 (以現在STL實作來講,要這個字串增加大小到夠大,讓他relocate) 回到正題,我個人是認為除非有很嚴重的向後相容考量 不然任何一個現代設計出來的class都不該吃const char* 也不該存const char* 因為實在沒有必要 另外一個常見的變種是傳回const char* 我以前有寫過一篇聊這個 http://rayer.logdown.com/posts/7801369 (無廣告,無流量問題) 除非是很特殊的情況,不然傳回const char*通常是個很麻煩的行為.... -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 1.164.141.110 ※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1537016499.A.D73.html ※ 編輯: Killercat (1.164.141.110), 09/15/2018 21:02:16