string::c_str()允许在堆上分配任何内容吗?

11
如果我需要在不分配任何内存的情况下从std::string中获取一个以NUL结尾的char数组,那么使用c_str是否安全?例如,如果我在析构函数中并且想要将一些数据从一个string复制到一个预先分配的固定大小的缓冲区中,我可以使用c_str并确保它不会抛出任何异常吗?
4个回答

7
标准规定调用c_str()可能会使得指向string元素的引用、指针和迭代器失效,这意味着重新分配是允许的(21.3/5“基本字符串类模板”)。
您可能只想调用string::copy()来获取副本(如果需要,您需要自己添加空终止符)。

使用string::copy()的建议非常有用。谢谢! - Pillsy

6
不,C++标准没有这样的保证。C++标准唯一的保证是返回值指向一个具有与std::string相同内容的char数组,并带有一个空终止符。
因此,如果实现以某种方式存储其内部表示形式而不是C字符串,并在调用c_str时动态分配C字符串,则符合标准,尽管我相当确定没有广泛使用的STL实现会这样做。
现在,关于C++0x,我听说(尽管我目前找不到相关文件),其中之一的更改将要求std::string在连续存储器上运行(对于std::vector已经存在类似的要求)。因此,在这种情况下,您可以访问从&str[0]到&str[0]+str.length()-1的跨度,就像它是一个没有空终止符的C字符串一样。

1
关于连续存储的要求,是的,C++0x N3126在21.4.1/5中指出:“basic_string对象中的char-like对象必须被连续存储。” - Cubbi

2

这个标准对此没有明确规定:

21.3.6 [lib.strings.ops]

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

2 要求:程序不得更改数组中存储的任何值。在调用指定与此对象相同的基本字符串类的非 const 成员函数之后,程序也不得将返回的值视为有效指针值。

虽然可以这样做,但我从未见过任何实现这样做的情况。

如果您关心这个问题,您可能希望考虑使用 vector<char> 代替 string,并执行以下操作:

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

这里的关键是知道何时以及如何处理需要以'\0'结尾的字符串。

1

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

指向basic_string序列元素的引用、指针和迭代器可能会因为以下对basic_string对象的使用而失效:
[ ... ]
— 调用data()和c_str()成员函数。

它允许使指针、引用和迭代器无效,以允许实现在调用c_str时重新分配用于存储字符串的内存。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接