C/C++:string.c_str()
今天忽然想起之前的一个小问题:
string.c_str()返回值失效的问题。
关于string.c_str()我个人认为,能多快将其拷贝到一个安全的地方,就尽快将其拷贝吧!
题外话:
其实例如Lua对C的接口中:lua_pushstring (lua_State *L, const char *s)中,就是把字符串s拷贝到栈上,然后返回。
在这里就类似strcpy等将c_str()的内容拷贝出来了,也就“放心了”!
请看如下代码:
string foo()
{
string s_subfun = "hello, world!";
return s_subfun;
}
int main()
{
string s_mainfun = foo();
return 0;
}
注意,实际上涉及到了三个string对象:
1.s_subfun;
2.s_mainfun;
3.是在foo函数返回时,还会创建一个新的临时对象。
恩,上面要注意第三点,是个临时对象。
如何使用c_str()最保险?
就如同上面的Code一样:
string s_mainfun = foo();
关键是要有一个自己声明的对象来接收foo()返回的值(姑且这么叫吧)。
用s_mainfun来接收了foo()返回的值。
以下使用是有问题的:
string foo()
{
string s_subfun = "hello, world!";
return s_subfun;
}
int main()
{
const char *s = (foo() + "test1280").c_str();
cout<<s<<endl;
return 0;
}
我这里虽然能正常输出,但是我认为其极有可能出问题(事实上就是会出问题)。
因为在+的地方实际是新构建了一个临时对象,然后对其进行c_str()调用,然后返回c_str()的值,然后:
这个临时变量析构,但是是在啥时候析构?能保证一定在当前的栈调用完毕时才析构吗?不知道!
但是不论如何,有两条准则是很重要的:
1.在调用c_str()时,注意其对象的状态,是个临时变量还是个局部变量?
2.调用c_str()后,尽可能快地用strcpy等拷贝函数将其拷贝到一个自己“放心”的地方,这不就是君子不立危墙之下吗?
还有几点需要说下。
(1)
string.c_str()返回的是一个const类型值,你说你将其强制转换成非const然后再操作是个啥意思?
int main()
{
string str = "test1280";
char *s = (char *)str.c_str();
cout<<str<<endl;
s[0] = 'n';
cout<<str<<endl;
}
Output:
test1280
nest1280
(2)
对字符串的修改可能改变c_str()返回值指向的字符串的内容。
int main()
{
string str = "test1280";
const char *s = str.c_str();
cout<<s<<endl;
str[2] = 'x';
cout<<s<<endl;
}
Output:
test1280
text1280
还是那句话:要尽可能快地用strcpy等拷贝c_str()指向的字符串到咱自己地盘,这才放心!
你不知道(记不清),啥时候你就不小心改了字符串string了,而这个有可能影响c_str()指向的字符串的值。
Reference:
从 c_str() 获得的指针可能被下列行为非法化:
传递给任何非标准库函数字符串的非 const 引用,或
在字符串上调用非 const 成员函数,包括 operator[] 、 at() 、 front() 、 back() 、 begin() 、 rbegin() 、 end() 及 rend() 。
通过 c_str() 写入字符数组是未定义行为。
回归原主题:
对c_str()的使用,要注意其对象的状态,是临时变量还是局部变量?
能确定c_str()后,要尽可能将其复制出来,万一你不小心改变了对象的值,会导致c_str()指向的字符数组内容发生改变~失效!
参考资料:
1.http://blog.youkuaiyun.com/nemo2011/article/details/19921605
2.https://my.oschina.net/ioslighter/blog/361046
3.http://blog.youkuaiyun.com/wangshubo1989/article/details/50286985
4.http://blog.youkuaiyun.com/u013682388/article/details/39547773