我读过几篇文章,其中提到c_str()和data()(在STL和其他实现中)的区别在于c_str()始终以空字符结尾,而data()则不是。
就我在实际实现中看到的情况,它们要么相同,要么data()调用c_str()。
我错过了什么?在哪些场景中使用哪一个更正确?
c_str()
。data()
,则您不必担心,如果您不需要字符串以空终止,则仍然使用 data()
,在某些实现中,它可能比c_str()执行得更好。data()
更有意义。在我的观点中,c_str()
只在您的字符串元素基于字符时才真正有用。data
现在需要以null结尾。根据cppreference的说法:“返回的数组以null结尾,即,data()和c_str()执行相同的功能。”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,使得对于每个
i
在[0,size()]
中,p + i == &operator[](i)
。
21.4.5 basic_string元素访问 [string.access]
const_reference operator[](size_type pos) const noexcept;
1 要求:pos <= size()。 2 返回值:如果pos < size(),则返回
*(begin() + pos)
,否则返回一个类型为T的对象的引用, 其值为charT();
所引用的值不得被修改。
std::string
为尾部的 '\0'
分配一个额外的字符。当你执行 std::string s("\0");
时,保证 s.data()[0]
和 s.data()[1]
都等于0。 - bcrist即使您看到它们执行相同的操作,或者.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()复制它们的内部缓冲区,或者使用两个缓冲区。而使用单个空终止符缓冲区意味着在实现std::string时只需使用一个内部缓冲区。
strcpy(sz, s.data())
可能是错误的,因为在C++11之前,std::data()
不能保证以空字符结尾。我的理解正确吗? - Johnconst
和non-const
重载都可用。 - TonySalimistring::substr
可以在内部保存对共享字符串数据的引用以及开始/结束范围,避免实际字符串数据的复制(和额外的分配)。如果涉及的子字符串仅被读取,则实现将推迟复制,直到你调用 c_str
或修改任何字符串为止,永远不会进行复制。string::data
允许不同的内部表示,例如绳索(字符串段的链接列表)。这可以显著改善插入/替换操作。再次强调,当你调用 c_str
或 data
时,段列表必须被合并为单个段。引用自 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.
.data()
方法现在也有一个非const的重载版本,因此对于非常量字符串来说,它们不再是等价的。 - Deduplicatorstd::basic_string<T>
具有向量没有的功能,例如它很容易连接字符串。 - Bolpat