字符串 c_str() vs

我已经阅读了一些地方,c_str()data()(在 STL 和其他实现中)之间的区别是,c_str()总是以 null 结束,而 data()不是。 就我在实际实现中看到的而言,它们要么执行相同的调用,要么执行 data()调用 c_str()

我错过了什么? 在什么情况下使用哪一个更正确?

60288 次浏览

文档是正确的。如果需要以空结尾的字符串,请使用 c_str()

如果实现者碰巧根据 c_str()实现了 data(),您不必担心,如果不需要字符串以 null 结束,那么仍然使用 data(),在某些实现中,它可能比 c _ str ()执行得更好。

字符串不一定要由字符数据组成,它们可以由任何类型的元素组成。在这些情况下,data()更有意义。在我看来,只有当字符串的元素是基于字符的时候,c_str()才是真正有用的。

号外 : 在 C + + 11以后,这两个函数必须是相同的。也就是说,data现在需要以 null 结尾。根据 首选: “返回的数组以 null 结尾,即 data ()和 c _ str ()执行相同的函数。”

即使你知道他们也会这么做。Data ()调用。C _ str () ,假设其他编译器也是这种情况是不正确的。您的编译器也有可能随着将来的版本而改变。

使用 std: : string 的2个理由:

字符串可用于文本和任意二进制数据。

//Example 1
//Plain text:
std::string s1;
s1 = "abc";


//Example 2
//Arbitrary binary data:
std::string s2;
s2.append("a\0b\0b\0", 6);

在使用字符串作为示例1时,应该使用. c _ str ()方法。

你应该使用。使用字符串作为示例2时,使用 data ()方法。不是因为使用它有危险。在这些情况下使用 c _ str () ,但是因为您使用二进制数据来让其他人查看您的代码更加明确。

使用. data () 可能存在的缺陷

下面的代码是错误的,可能会导致程序中出现 Segfault:

std::string s;
s = "abc";
char sz[512];
strcpy(sz, s.data());//This could crash depending on the implementation of .data()

为什么实现者常常让. data ()和. c _ str ()做同样的事情?

因为这样做效率更高。唯一的办法。Data ()返回一些不以 null 结束的东西,将会有。C _ str ()或。Data ()复制它们的内部缓冲区,或者只使用2个缓冲区。拥有一个以空结束的缓冲区总是意味着在实现 std: : string 时总是可以只使用一个内部缓冲区。

引自 ANSI ISO IEC 14882 2003(C + + 03标准) :

    21.3.6 basic_string string operations [lib.string.ops]


const charT* c_str() const;


Returns: A pointer to the initial element of an array of length size() + 1 whose first size() elements
equal the corresponding elements of the string controlled by *this and whose last element is a
null character specified by charT().
Requires: The program shall not alter any of the values stored in the array. Nor shall the program treat the
returned value as a valid pointer value after any subsequent call to a non-const member function of the
class basic_string that designates the same object as this.


const charT* data() const;


Returns: If size() is nonzero, the member returns a pointer to the initial element of an array whose first
size() elements equal the corresponding elements of the string controlled by *this. If size() is
zero, the member returns a non-null pointer that is copyable and can have zero added to it.
Requires: The program shall not alter any of the values stored in the character array. Nor shall the program
treat the returned value as a valid pointer value after any subsequent call to a non- const member
function of basic_string that designates the same object as this.

这个问题已经得到了回答,一些笔记的目的是: 执行自由。

std::string操作——例如迭代、串联和元素变异——不需要零结束符。除非将 string传递给一个期望以零结尾的字符串的函数,否则可以省略它。

这将允许实现让子字符串共享实际的字符串数据: string::substr可以在内部保存对共享字符串数据和起始/结束范围的引用,从而避免复制(和额外的分配)实际的字符串数据。实现会将副本推迟到调用 c_str或修改任何字符串之后再执行。如果只读所涉及的子字符串,则不会产生任何副本。

(在多线程环境中,写上复制的实现没有多少乐趣,而且典型的内存/分配节省不值得现在使用更复杂的代码,所以很少这样做)。


类似地,string::data允许一种不同的内部表示形式,例如,攀援(字符串段的链表)。这可以显著改进插入/替换操作。同样,当您调用 c_strdata时,段列表必须折叠为单个段。

C + + 11/C + + 0x中,data()c_str()不再有区别。因此,data()也需要在末尾有一个空终止。

21.4.7.1 basic_string访问器[ string.accessor ]

const charT* c_str() const noexcept;

const charT* data() const noexcept;

返回: 一个指针 p,使得 [0,size()]中每个 ip + i == &operator[](i)


21.4.5 basic _ string element access [ string.access ]

const_reference operator[](size_type pos) const noexcept;

1要求: pos < = size ()。 返回: *(begin() + pos) if pos < size(),否则为对 T 类型对象的引用 值 charT();的参考值不得修改。

前面的所有注释都是一致的,但是我还想补充一点,从 c + + 17开始,str.data ()返回一个 char * 而不是 const char *