修改c ++字符串对象的底层char数组

Nee*_*eed 10 c++ arrays string

我的代码是这样的:

string s = "abc";
char* pc = const_cast<char*>( s.c_str() );
pc[ 1 ] = 'x';
cout << s << endl;
Run Code Online (Sandbox Code Playgroud)

当我使用GCC编译上面的代码片段时,我得到了结果"axc",如预期的那样.我的问题是,char以这种方式修改C++字符串的底层数组是否安全且可移植?或者可能有其他方法直接操作字符串的数据?

仅供参考,我的目的是编写一些可以由C和C++调用的纯C函数,因此,它们只能char*作为参数接受.从char*字符串到字符串,我知道涉及复制,惩罚是不利的.所以,任何人都可以提出一些建议来处理这种情况.

Lig*_*ica 5

(a)这不一定是基础字符串.std::string::c_str()应该是底层字符串的副本(虽然C++标准中的错误意味着,实际上,它通常不是......我相信这在C++ 0x中已得到修复).

(b)const_cast远离constness只破解变量类型:实际对象仍然存在const,而你修改它是未定义的行为 - 非常糟糕.

简单地说,要这样做.


你可以用&myString[0]吗?它有一个非const版本; 然后,它被声明与data()[0]没有非const版本相同.有一个像样的库参考手的人可以清除这一点.


Ste*_*sop 5

对于第一部分,c_str()返回const char*它意味着它所说的.const_cast在这种情况下,所有实现的是您的未定义行为编译.

对于第二部分,在C++中,0x std::string保证具有连续存储,就像std::vector在C++ 03中一样.因此,你可以使用&s[0]得到char*传递给你的函数,只要字符串不是空的.在实践中,string目前处于活跃开发阶段的所有实施已经具有连续存储:在标准委员会会议上进行了一次民意调查,没有人提供反例.因此,如果您愿意,可以立即使用此功能.

但是,std::string使用来自C风格字符串的根本不同的字符串格式,即它的数据+长度而不是nul-terminated.如果从C函数修改字符串数据,则无法更改字符串的长度,并且无法确定最后是否为空字节c_str().并且std::string可以包含作为数据一部分的嵌入式nuls,所以即使你确实找到了一个nul,在不知道长度的情况下你仍然不知道你已经找到了字符串的结尾.对于能够在不同类型的数据上正确运行的函数,您可以做的非常有限.


Oli*_*rth 1

这依赖于未定义的行为,因此不可移植。