※ 引述《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