以前一直使用string::data()函数没发现什么问题,前天居然发现string::data不能用了,也就是data()返回没有结束符,导致拷贝崩溃,后来一查,这个data函数返回是不一定会包含结束符的。写本文专门写了个测试程序去复现,测试程序却又带\0结束符返回,编译器什么都没换过(指教)。
不过不管怎样,还是使用c_str()保险,对涉及中间带\0的string,使用data()时,注意结合len来进行安全限定。
一、string::data不带结束符、string::c_str带结束符
这是:
http://www.cplusplus.com/reference/string/string/data/
http://www.cplusplus.com/reference/string/string/c_str/
说法,而天缘实际测试,这个data函数还是有\0添加返回的。测试程序如下:
#include <iostream>
#include <string>
using namespace std;
bool fun(string x) {
const char* p=x.data();
return true;
}
void main() {
string s1 = "98765432109876543210A";
char* s2 = "12345";
char s3[] = "12345";
char res[255];
int len1 = s1.length(); //=21, no(or not including) '\0'(terminating null character)
int len2 = strlen(s2); //=5, no(or not including) '\0'
int len3 = strlen(s3); //=5, no(or not including) '\0'
const char* abuf = s1.c_str(); //append '\0'
strcpy(res,abuf); //ok, find '\0'
const char* bbuf = s1.data(); //find '\0' (maybe no)
strcpy(res,s1.data()); //Do not use this
string s4 = "12345 \0 54321"; //s4="12345 "
size_t len=s4.length(); //=6
size_t size=s4.size(); //=6
const char*ps=s4.c_str();
string s5= string("12345 \0 54321", 13);//s5=12345 \0 54321
//const char*pd=s5.data();
fun(s5);
}
但确实也遇到过没有结束符返回的情况,好像内容很长时(函数引用?...),当时就因为没有结束符导致拷贝崩溃。后来全部换成c_str()了。
二、勿通过string::data、string::c_str返回指针修改string内容
也就是说data()和c_str()只供引用使用。而且一旦string内容变动,则必须重新获取该指针。string对象的赋值,必须使用符合string类规则的处理方式,比如构造、append、erase等函数进行。
具体参考:http://www.cplusplus.com/reference/string/string/
三、中间带\0结束符的string对象
有多种方法可实现中间带结束符\0的string对象初始化。但是像:
string s="123 \0 123"; s5="abc\0"; s5+="def\0";
这样的初始化方法都是不行的,因为编译器或运行时默认都会截掉结束符后面的字符串。结果就是:
s="123 "
s5="abcdef"
1、构造法初始化
string s5= string("12345 \0 54321", 13);
这样的方式初始化,这时 s5="12345 \0 54321"
2、append函数添加
除了上面方法,还可以使用append函数,代码如下:
s5.append("abc\0",4);
s5.append("def\0",4);
本文探讨了C++中string::data与string::c_str的区别及使用注意事项,特别是data可能不含结束符的问题,并提供了安全使用建议。
789

被折叠的 条评论
为什么被折叠?



