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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 13:36:15  来源:igfitidea点击:

string c_str() vs. data()

c++stlc-str

提问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. datais 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_stringaccessors [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 each iin [0,size()].

21.4.7.1basic_string访问器 [string.accessors]

const charT* c_str() const noexcept;

const charT* data() const noexcept;

1 返回: 一个指针 p 使得p + i == &operator[](i)对于每个iin [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 value charT();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("a
std::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::stringoperations - e.g. iteration, concatenation and element mutation - don't need the zero terminator. Unless you pass the stringto 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::substrcould 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::dataallows 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_stror 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*