问题 string :: c_str()是否允许在堆上分配任何东西?


如果我需要终止NUL char 阵列出一个 std::string 在我需要确保没有分配任何东西的情况下,使用是否安全 c_str 这样做?例如,如果我在析构函数中,我想复制一些数据 string 进入预先分配的固定大小的缓冲区,我可以使用 c_str 并确保它不会扔任何东西?


10239
2017-09-29 15:23


起源



答案:


标准说要打电话 c_str() 可能会引用引用元素的引用,指针和指针无效 string,这意味着允许reallaocation(21.3 / 5“类模板basic_string”)。

你可能想打电话 string::copy() 得到你的副本(如果你需要,你需要自己添加空终止符)。


6
2017-09-29 15:30



建议使用 string::copy() 特别有用。谢谢! - Pillsy


答案:


标准说要打电话 c_str() 可能会引用引用元素的引用,指针和指针无效 string,这意味着允许reallaocation(21.3 / 5“类模板basic_string”)。

你可能想打电话 string::copy() 得到你的副本(如果你需要,你需要自己添加空终止符)。


6
2017-09-29 15:30



建议使用 string::copy() 特别有用。谢谢! - Pillsy


不,标准没有这样的保证。 C ++标准中唯一的保证是返回值指向a char 数组与内容相同 std::string,加上一个nul-terminator。

因此,符合标准的实现以某种方式存储其内部表示而不是C字符串,并在您调用时动态分配C字符串 c_str虽然我很确定没有广泛使用的STL实现实际上这样做。

现在,关于C ++ 0x,我听说过(虽然我现在不知道为此找到文档),其中一个变化是要求 std::string 在连续存储上运行(类似的要求已经存在 std::vector)。因此,在这种情况下,您可以从中访问范围 &str[0] 通过 &str[0]+str.length()-1 好像它是一个没有nul-terminator的C字符串。


6
2017-09-29 15:29



关于连续存储的要求,是的,C ++ 0x N3126说 21.4.1/5,“basic_string对象中的类似char的对象应该连续存储。” - Cubbi


标准对此保持沉默:

21.3.6 [lib.strings.ops]

const charT * c_str()const; 1   返回:指向初始的指针   长度为(+)的数组的元素   1的第一个size()元素相等   相应的元素   字符串由* this和其控制   最后一个元素是一个空字符   由charT()指定。

2要求:程序不得   改变存储在中的任何值   阵列。该计划也不应该对待   返回值作为有效指针   任何后续调用a后的值   类的非const成员函数   basic_string指定相同的   对象就是这样。

它可以。也就是说,我从来没有见过任何实现。

如果您担心这一点,您可能需要考虑使用 vector<char> 代替 string,做一些像:

vector<char> chars;
// ...
char* my_str = &chars[0];

这里的诀窍是知道何时以及如何处理需求 '\0' - 终止字符串。


2
2017-09-29 15:33





标准除了明确表示字符串可以在调用时分配内存 c_str。特别是,它说(§21.3/ 5):

引用basic_string序列元素的引用,指针和迭代器可能会被该basic_string对象的以下用法无效:
  [...]
   - 调用data()和c_str()成员函数。

它允许指针,引用和迭代器失效 特别 允许实现在您调用时重新分配用于存储字符串的内存 c_str


1
2017-09-29 15:41