stringc_str()与数据()

我已经读了几个地方, c_str()data() (在STL和其他实现)之间的区别是, c_str()总是空终止,而data()不是。 就我在实际实现中看到的,它们要么执行相同的操作,要么调用c_str()

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

该文件是正确的。 如果你想要一个以空字符结尾的string,可以使用c_str()

如果实现者以c_str()方式实现data() ,则不必担心,如果不需要string被null终止,仍然使用data() ,在某些实现中可能会执行比c_str()更好。

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

额外 :在C ++ 11之后,两个函数都要求是相同的。 即data现在需要以空终止。 根据cppreference :“返回的数组是空终止的,即data()和c_str()执行相同的function。

在C ++ 11 / C ++ 0x中 , data()c_str()不再相同。 因此data()也需要在最后有一个空终止。

21.4.7.1 basic_string访问器[string.accessors]

const charT* c_str() const noexcept;

const charT* data() const noexcept;

1返回:对于[0,size()]每个i ,指针p使得p + i == &operator[](i)


21.4.5 basic_string元素的访问[string.access]

const_reference operator[](size_type pos) const noexcept;

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

即使知道你已经看到他们做了同样的事情,或者.data()调用.c_str(),假设这是其他编译器的情况是不正确的。 您的编译器也可能随着将来的版本而改变。

使用std :: string的两个原因:

std :: string可以用于文本和任意二进制数据。

 //Example 1 //Plain text: std::string s1; s1 = "abc"; //Example 2 //Arbitrary binary data: std::string s2; s2.append("a\0b\0b\0", 6); 

当您使用string作为示例1时,应该使用.c_str()方法。

当您使用string作为示例2时,应该使用.data()方法。并不是因为在这些情况下使用.c_str()是危险的,而是因为它更明确地表明您正在使用二进制数据供其他人查看你的代码。

使用.data()可能的缺陷

下面的代码是错误的,并可能导致程序中的段错误:

 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时总是只使用一个内部缓冲区。

已经有了答复,目的是:执行的自由。

std::string操作 – 例如迭代,连接和元素变换 – 不需要零终止符。 除非您将该string传递给期望零终止string的函数,否则可以省略。

这将允许一个实现使子string共享实际的string数据: string::substr可以在内部持有对共享string数据的引用,以及开始/结束范围,避免实际string数据的复制(和额外分配)。 实现将延迟副本,直到您调用c_str或修改任何string。 如果所涉及的字形只是被读取,则不会有任何副本。

(写时复制的实现在multithreading环境中没有太多的乐趣,而且典型的内存/分配节约不值得今天更复杂的代码,所以很less这样做)。


类似地, string::data允许不同的内部表示,例如一个绳索(链接段链表)。 这可以显着改善插入/replace操作。 同样,当您调用c_strdata时,段的列表将不得不被折叠为一个段。

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. 
Interesting Posts