string c_str()与data()

时间:2008-10-11 20:59:20

标签: c++ stl c-str

我已经阅读了几个地方,c_str()data()(在STL和其他实现中)之间的区别在于c_str()始终为空终止而data()不是。 就我在实际实施中看到的情况而言,他们要么做同样的事情,要么data()来电c_str()

我在这里缺少什么? 在哪种情况下使用哪一种更正确?

6 个答案:

答案 0 :(得分:97)

文档是正确的。如果要使用空终止字符串,请使用c_str()

如果实施者按c_str()方式实施data()您不必担心,如果您不需要将字符串空终止,仍然使用data(),在某些实现中,它可能比c_str()更好地执行。

字符串不一定必须由字符数据组成,它们可以由任何类型的元素组成。在这些情况下,data()更有意义。我认为c_str()仅在字符串的元素基于字符时才真正有用。

额外:在C ++ 11以后,两个函数都必须相同。即data现在必须以空终止。根据{{​​3}}:“返回的数组以空值终止,即data()和c_str()执行相同的功能。”

答案 1 :(得分:25)

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返回:指针p,p + i == &operator[](i)中每i[0,size()]


  

21.4.5 basic_string元素访问[string.access]

     

const_reference operator[](size_type pos) const noexcept;

     

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

答案 2 :(得分:18)

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

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

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);

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

当您使用字符串作为示例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()返回非空终止的东西的唯一方法是让.c_str()或.data()复制它们的内部缓冲区,或者只使用2个缓冲区。具有单个空终止缓冲区始终意味着在实现std :: string时始终只能使用一个内部缓冲区。

答案 3 :(得分:3)

已经有人回答了一些关于目的的说明:实施自由。

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

这将允许实现让子串共享实际的字符串数据:string::substr可以在内部持有对共享字符串数据的引用,以及开始/结束范围,避免实际的副本(和附加分配)字符串数据。实现将推迟复制,直到您调用c_str或修改任何字符串。如果只涉及所涉及的标志,则不会复制。

(在多线程环境中,copy-on-write实现并不是很有趣,加上典型的内存/分配节省不值得今天更复杂的代码,所以很少这样做。)


类似地,string::data允许不同的内部表示,例如一根绳子(字符串段的链表)。这可以显着改善插入/更换操作。再次,当您致电c_strdata时,必须将细分列表折叠为单个细分。

答案 4 :(得分:2)

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

答案 5 :(得分:1)

引自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.