C++ 字符串 c_str() 与 data()
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/194634/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
string c_str() vs. data()
提问by Scott Langham
I have read several places that the difference between c_str()
and data()
(in STL and other implementations) is that c_str()
is always null terminated while data()
is not.
As far as I have seen in actual implementations, they either do the same or data()
calls c_str()
.
我读过几个地方,c_str()
和data()
(在 STL 和其他实现中)之间的区别在于c_str()
总是以空结尾而data()
不是。就我在实际实现中所见,它们要么执行相同操作,要么data()
调用c_str()
.
What am I missing here? Which one is more correct to use in which scenarios?
我在这里缺少什么?在哪些场景下使用哪个更正确?
回答by Scott Langham
The documentation is correct. Use c_str()
if you want a null terminated string.
文档是正确的。使用c_str()
,如果你想有一个空结束的字符串。
If the implementers happend to implement data()
in terms of c_str()
you don't have to worry, still use data()
if you don't need the string to be null terminated, in some implementation it may turn out to perform better than c_str().
如果实现者碰巧实现data()
了c_str()
你不必担心,data()
如果你不需要字符串以空终止,仍然使用,在某些实现中它可能比 c_str() 执行得更好。
strings don't necessarily have to be composed of character data, they could be composed with elements of any type. In those cases data()
is more meaningful. c_str()
in my opinion is only really useful when the elements of your string are character based.
字符串不一定必须由字符数据组成,它们可以由任何类型的元素组成。在那些情况下data()
更有意义。c_str()
在我看来,只有当您的字符串元素基于字符时才真正有用。
Extra: In C++11 onwards, both functions are required to be the same. i.e. data
is now required to be null-terminated. According to cppreference: "The returned array is null-terminated, that is, data() and c_str() perform the same function."
额外:在 C++11 以后,两个函数必须相同。iedata
现在需要以空值结尾。根据cppreference:“返回的数组是空终止的,即 data() 和 c_str() 执行相同的功能。”
回答by mfazekas
In C++11/C++0x, data()
and c_str()
is no longer different. And thus data()
is required to have a null termination at the end as well.
在C ++ 11 / C ++ 0x中,data()
并且c_str()
不再不同。因此data()
也需要在最后有一个空终止。
21.4.7.1
basic_string
accessors [string.accessors]
const charT* c_str() const noexcept;
const charT* data() const noexcept;
1 Returns: A pointer p such that
p + i == &operator[](i)
for eachi
in[0,size()]
.
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
in[0,size()]
。
21.4.5 basic_string element access [string.access]
const_reference operator[](size_type pos) const noexcept;
1 Requires: pos <= size(). 2 Returns:
*(begin() + pos) if pos < size()
, otherwise a reference to an object of type T with valuecharT();
the referenced value shall not be modi?ed.
21.4.5 basic_string 元素访问 [string.access]
const_reference operator[](size_type pos) const noexcept;
1 要求:pos <= size()。2 返回:
*(begin() + pos) if pos < size()
,否则对具有值charT();
的T 类型对象的引用不应修改所引用的值。
回答by Brian R. Bondy
Even know you have seen that they do the same, or that .data() calls .c_str(), it is not correct to assume that this will be the case for other compilers. It is also possible that your compiler will change with a future release.
即使知道你已经看到它们做了同样的事情,或者 .data() 调用 .c_str(),假设其他编译器也是这种情况是不正确的。您的编译器也可能会随着未来的版本而改变。
2 reasons to use std::string:
使用 std::string 的 2 个理由:
std::string can be used for both text and arbitrary binary data.
std::string 可用于文本和任意二进制数据。
//Example 1
//Plain text:
std::string s1;
s1 = "abc";
//Example 2
//Arbitrary binary data:
std::string s2;
s2.append("astd::string s;
s = "abc";
char sz[512];
strcpy(sz, s.data());//This could crash depending on the implementation of .data()
b 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.
b##代码##", 6);
You should use the .c_str() method when you are using your string as example 1.
当您将字符串用作示例 1 时,您应该使用 .c_str() 方法。
You should use the .data() method when you are using your string as example 2. Not because it is dangereous to use .c_str() in these cases, but because it is more explicit that you are working with binary data for others reviewing your code.
当您使用字符串作为示例 2 时,您应该使用 .data() 方法。不是因为在这些情况下使用 .c_str() 很危险,而是因为您正在使用二进制数据供其他人查看更为明确你的代码。
Possible pitfall with using .data()
使用 .data() 的可能陷阱
The following code is wrong and could cause a segfault in your program:
以下代码是错误的,可能会导致您的程序出现段错误:
##代码##Why is it common for implementers to make .data() and .c_str() do the same thing?
为什么实现者让 .data() 和 .c_str() 做同样的事情很常见?
Because it is more efficient to do so. The only way to make .data() return something that is not null terminated, would be to have .c_str() or .data() copy their internal buffer, or to just use 2 buffers. Having a single null terminated buffer always means that you can always use just one internal buffer when implementing std::string.
因为这样做效率更高。使 .data() 返回非空终止的东西的唯一方法是让 .c_str() 或 .data() 复制它们的内部缓冲区,或者只使用 2 个缓冲区。拥有一个空终止缓冲区总是意味着在实现 std::string 时你总是可以只使用一个内部缓冲区。
回答by peterchen
It has been answered already, some notes on the purpose: Freedom of implementation.
已经回答了,关于目的的一些说明:实施自由。
std::string
operations - e.g. iteration, concatenation and element mutation - don't need the zero terminator. Unless you pass the string
to a function expecting a zero terminated string, it can be omitted.
std::string
操作——例如迭代、串联和元素突变——不需要零终止符。除非您将 传递string
给需要零终止字符串的函数,否则可以省略它。
This would allow an implementation to have substrings share the actual string data: string::substr
could internally hold a reference to shared string data, and the start/end range, avoiding the copy (and additional allocation) of the actual string data. The implementation would defer the copy until you call c_str or modify any of the strings. No copy would ever be made if the strigns involved are just read.
这将允许实现让子字符串共享实际的字符串数据:string::substr
可以在内部保存对共享字符串数据的引用,以及开始/结束范围,避免实际字符串数据的复制(和额外分配)。该实现将推迟复制,直到您调用 c_str 或修改任何字符串。如果只是阅读所涉及的字符串,则永远不会复制。
(copy-on-write implementation aren't much fun in multithreaded environments, plus the typical memory/allocation savings aren't worth the more complex code today, so it's rarely done).
(写时复制实现在多线程环境中并不是很有趣,加上典型的内存/分配节省不值得今天更复杂的代码,所以很少这样做)。
Similarly, string::data
allows a different internal representation, e.g. a rope (linked list of string segments). This can improve insert / replace operations significantly. again, the list of segments would have to be collapsed to a single segment when you call c_str
or data
.
类似地,string::data
允许不同的内部表示,例如绳索(字符串段的链表)。这可以显着改善插入/替换操作。同样,当您调用c_str
或时,段列表必须折叠为单个段data
。
回答by Mihran Hovsepyan
Quote from ANSI ISO IEC 14882 2003
(C++03 Standard):
引自ANSI ISO IEC 14882 2003
(C++03 标准):
回答by Nam Vu
All the previous commments are consistence, but I'd also like to add that starting in c++17, str.data() returns a char* instead of const char*
之前的所有评论都是一致的,但我还想补充一点,从 c++17 开始,str.data() 返回一个 char* 而不是 const char*