是否“&S [0]”指向相邻字符中的std :: string?
题
我在做一些维护工作,跑过像下面这样:
std::string s;
s.resize( strLength );
// strLength is a size_t with the length of a C string in it.
memcpy( &s[0], str, strLength );
我知道使用&S [0]将是安全的,如果它是一个std ::矢量,但是这是一个安全使用的std :: string的?
解决方案
一个的std :: string的分配不是保证是C ++ 98/03标准下是连续的,但C ++ 11点的力的那样。在实践中,无论是我还是香草萨特知道不使用连续的存储的实现的。
注意,&s[0]
事情所以总能保证由C ++ 11标准,即使在0长度的字符串的情况下的工作。如果你没有str.begin()
或&*str.begin()
这将无法得到保证,但对于&s[0]
该标准定义了operator[]
为:
返回:如果
*(begin() + pos)
pos < size()
,否则与值T
类型charT()
的一个对象的引用;所引用的值不应当被修改
继续,data()
定义为:
返回:的指针
p
使得p + i == &operator[](i)
用于i
每个[0,size()]
(通知方括号在该范围的两端)
的通知的:预标准化的C ++ 0x并不能保证&s[0]
工作与零长度字符串(实际上,这是明确的未定义的行为),和这个答案的旧版本说明这一点;这已被固定在后一标准草案,所以答案已经相应地更新。
其他提示
从技术上讲,没有,因为不需要std::string
到连续存储在存储器中的内容。
然而,在几乎所有的实现(其中每一个我所知道的实现),内容连续存储,这将“工作。”
有安全使用。我想大多数的答案是一次正确的,但标准的改变。选自C引述++ 11标准, basic_string的一般要求[string.require] ,21.4.1.5表示:
炭样在basic_string的对象的对象将被连续地存储。也就是说,对于任何的basic_string 对象s时,身份&*(s.begin()+ N)==&* s.begin()+ N应的n个,使得0的所有值保持 <= N
在此之前的位,它说,所有迭代器是随机访问迭代。这两位都支持你问题的用法。 (此外,显然斯特劳斯使用它在他的最新著作;))
这不是不可能的,这种变化是在C ++ 11完成。我似乎记得加入同一保证然后矢量,这也得到了非常有用的数据()的指针与该释放。
希望有所帮助。
读者应该注意,这个问题被要求在2009年,当C ++ 03标准是当前出版物。此答案是基于该版本的标准,其中std::string
s是不保证利用连续的存储。由于这个问题是不是在一个特定的平台(如GCC)的情况下问,我并没有对OP的平台的假设 - 特别是天气或不是用于在string
contigious存储
法律?也许是,也许不是。安全?也许,但也许不是。良好的代码?好了,让我们不要去那里...
为什么不只是做:
std::string s = str;
...或:
std::string s(str);
...或:
std::string s;
std::copy( &str[0], &str[strLen], std::back_inserter(s));
...或:
std::string s;
s.assign( str, strLen );
中的代码可能会奏效,但更多的运气比判断,它使有关,不能保证实施的假设。我建议确定所述代码的有效性是无关紧要的,而它是在一个并发症无意义,很容易降低到刚刚:
std::string s( str ) ;
,或者如果分配给现有的std :: string对象,只是:
s = str ;
和然后让的std :: string本身确定如何实现的结果。如果你打算诉诸这种废话,那么你可能根本不使用的std :: string和棒子来,因为你重新引入所有C字符串相关的危险。
这通常是不的安全,而不管内部串序列是否被连续地或不存储在存储器中。有可能是涉及到如何控制序列由std::string
对象存储,除了连续性其他许多实施细节。
与一个真正的实用上的问题可能是以下内容。不需要std::string
的控制的序列将被存储为一个0结尾的字符串。然而,在实践中,许多(?大多数)实施选择1特大型内部缓冲区和存储序列反正0结尾的字符串,因为它简化c_str()
方法的实现:只返回一个指向内部缓冲区和你完成。
您在您的问题没有做任何努力去引用的代码零终止数据被复制到内部缓冲区。很有可能它根本不知道零终止是否有必要对这个实现std::string
的。很可能它依赖于充满调用resize
后零内部缓冲区,所以分配给由实现零终止多余的字符被方便地预先设置为零。这一切是一个实现细节,这意味着该技术依赖于一些比较脆弱的假设。
在换句话说,在一些实施中,你可能不得不使用strcpy
,不memcpy
的数据强行进入这样的控制序列。而在一些其他实现,你不得不使用memcpy
而不是strcpy
。