std :: string :: c_str&Null终止

tuk*_*tuk 5 c++ string c-str

我已经阅读了各种描述,std::string::c_str包括多年来/几十年来提出的问题,

我清楚地喜欢这个描述:

返回指向数组的指针,该数组包含表示字符串对象当前值的以空字符结尾的字符序列(即C字符串).此数组包含组成字符串对象值的相同字符序列以及末尾的附加终止空字符('\ 0').

然而,关于此功能目的的一些事情仍然不清楚.

你可以原谅认为调用c_str可能会\0在字符串的末尾添加一个字符,该字符存储在host对象的内部char数组中(std::string):

s[s.size+1] = '\0'
Run Code Online (Sandbox Code Playgroud)

但是,std::string即使在调用之前,默认情况下对象仍然是Null终止c_str: 在此输入图像描述

看完定义后:

const _Elem *c_str() const _NOEXCEPT
{   // return pointer to null-terminated nonmutable array
    return (this->_Myptr());
}
Run Code Online (Sandbox Code Playgroud)

我没有看到任何代码会添加\0到char数组的末尾.据我所知,c_str只返回一个指向存储在数组的第一个元素中的char的指针begin().我甚至没有看到检查内部数组被终止的代码\0

或者我错过了什么?

das*_*ght 6

您没有看到添加'\0'到序列末尾的代码,因为空字符已存在.一个实现c_str无法返回指向新数组的指针,因此数组必须存储在std::string对象本身上.

因此,您有两种有效的方法来实现它:

  1. 始终存储'\0'_Myptr()构造中的字符数组的末尾,或
  2. 根据需要复制字符串,'\0'c_str()调用时添加,并在析构函数中删除副本.

第一种方法可以让你恢复_Myptr()c_str(),在存储每个字符串一个多余的字符为代价.第二种方法需要每个std::string对象一个额外的指针,因此第一种方法更便宜.


Pet*_*ter 6

在C++ 11之前,没有要求std::string(或模板化的类 std::basic_string- 其中std :: string是实例化)存储尾随'\0'.这反映在data()c_str()成员函数的不同规范中- data()返回指向底层数据的指针(不需要用a终止'\0'c_str()返回带有终止的副本'\0'.但是,同样地,没有要求不存储尾随'\0'内部(访问存储数据末尾的字符是未定义的行为).....并且,为简单起见,一些实现选择追加尾随'\0'.

使用C++ 11,这改变了.本质上,data()成员函数被指定为具有相同的效果c_str()(即返回的指针是具有尾随的数组的第一个字符'\0').这导致需要在'\0' 返回的数组上进行尾随data(),因此要求内部表示.

所以你看到的行为与C++ 11一致 - 类的一个不变量是尾随的'\0' (即构造函数确保是这种情况,修改字符串的成员函数确保它保持为真,以及所有公共成员函数)可以依靠它是真的).

您所看到的行为与C++ 11之前的C++标准并不矛盾.严格来说,std::string在C++ 11不需要保持跟踪之前'\0',同样,实现者可以选择这样做.