1. std::string 是否可以包含二进制字符,答案是能
std::string ss = std::string("XXX") + '\2' + "YYY" + '\11' + "ZZZ";
std::cout << "len=[" << ss.size() << "],data=[" << ss << "]";
// len=[11],data=[XXXYYY ZZZ]
2. std::string 是否可以包含字符0,答案是能
std::string ss = std::string("XXX") + '\0' + "YYY" + '\0' + "ZZZ";
std::cout << "len=[" << ss.size() << "],data=[" << ss << "]";
// len=[11],data=[XXXYYYZZZ]
3. 如何从char *构造std::string
3.1 整个字符串
const char * cc = "XXXYYYZZZ";
std::string ss(cc);
std::cout << "len=[" << ss.size() << "],data=[" << ss << "]" << std::endl;
// len=[9],data=[XXXYYYZZZ]
3.2 指定长度子串
const char * cc = "XXXYYYZZZ";
std::string ss(cc, 3);
std::cout << "len=[" << ss.size() << "],data=[" << ss << "]" << std::endl;
//
len=[3],data=[XXX]
3.3 指定起始位置长度子串
const char * cc = "XXXYYYZZZ";
std::string ss(cc + 3, 3);
std::cout << "len=[" << ss.size() << "],data=[" << ss << "]" << std::endl;
// len=[3],data=[YYY]
注意, 如果char *中包含'\0'字符, 那么到'\0'后面的内容会被丢弃, 比如
const char * cc = "XXXYYY\0ZZZ";
std::string ss(cc);
std::cout << "len=[" << ss.size() << "],data=[" << ss << "]" << std::endl;
// len=[6],data=[XXXYYY]
因为const char *包含'\0'字符, 后面的"ZZZ"被丢弃了。总结一句话如果char *里面包含'\0'字符,那么'\0'之后的内容会被丢弃。
因此如果你试图从buffer
unsigned char * buffer = ....
创建std::string对象采用buffer里面的一个字串 (offset, length)
std::string ss(buffer + offset, length);
如果在buffer + offset开始的length范围内存在一个'\0'字符; 那么ss可能不是你想要的结果, ss只包含从buffer+offset开始到'\0'字符为止, '\0'以后的字符尽管它还在length之内, 也会被丢弃。
C++之所以这样做是基于对char *规范的理解; char *的规范遇到'\0'表示char *结束; 也就是说'\0'之后的数据已经不属于char *的范围;因此任何试图基于char *构造的std::string对象都不应该去访问char *之外的数据; 这也就像strcpy和memcpy的区别一样。