作者Killercat (杀人猫™)
看板C_and_CPP
标题Re: [问题] string和c_str()的奇怪输出
时间Sat Sep 15 21:01:31 2018
※ 引述《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://webptt.com/cn.aspx?n=bbs/C_and_CPP/M.1537016499.A.D73.html
※ 编辑: Killercat (1.164.141.110), 09/15/2018 21:02:16