"&s [0]"是否指向std :: string中的连续字符?

pax*_*977 37 c++ stdstring memcpy c++03

我正在做一些维护工作,遇到类似以下的事情:

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 );
Run Code Online (Sandbox Code Playgroud)

我知道使用&s [0]如果它是std :: vector会是安全的,但是这是std :: string的安全使用吗?

Tod*_*ner 42

根据C++ 98/03标准,std :: string的分配不保证是连续的,但C++ 11强制它.在实践中,我和Herb Sutter都不知道不使用连续存储的实现.

请注意&s[0],即使在0长度字符串的情况下,也始终保证C++ 11标准能够工作.如果你做了str.begin()或不能保证&*str.begin(),但是对于&s[0]标准定义operator[]为:

返回:*(begin() + pos)if pos < size(),否则引用T具有值的类型的对象charT(); 参考值不得修改

继续,data()定义为:

返回:一个指针p,p + i == &operator[](i)用于每个iin [0,size()].

(注意范围两端的方括号)


注意:预标准化C++ 0x不能保证&s[0]使用零长度字符串(实际上,它是显式未定义的行为),并且这个答案的旧版本解释了这一点; 这已在以后的标准草案中修复,因此答案已相应更新.

  • 詹姆斯:几乎是因为`s [s.length()]`的null不必是连续的.`&s [n] + 1 ==&s [n + 1]`对于所有n,其中'0 <= n <s.length() - 1`必须为真.该要求隐藏在21.3.4/1中,`s [n]`必须返回与`s.data()[n]`相同的对象(对于n <length()),而data()必须是连续的. (5认同)
  • Sutter在对该帖子的评论中说,"当前的ISO C++确实要求&str [0]咳出一个指向连续字符串数据的指针(但不一定是空终止的!),"这实际上会使OP的用法正确.但是,我在标准中找不到任何说明的内容(至少它不在21.3.4 lib.string.access中). (3认同)

Jam*_*lis 7

从技术上讲,不,因为std::string不需要将其内容连续存储在内存中.

但是,在几乎所有实现中(我所知道的每个实现),内容都是连续存储的,这将"起作用".

  • 不.但如果你愿意,你可以做这样的实现. (2认同)

seb*_*mer 7

使用安全.我认为大多数答案都是正确的,但标准改变了.引用C++ 11标准,basic_string一般要求[string.require],21.4.1.5,说:

basic_string对象中的char类对象应连续存储.也就是说,对于任何basic_string对象,标识&*(s.begin()+ n)==&*s.begin()+ n应该适用于n的所有值,使得0 <= n <s.size ().

在此之前,它说所有迭代器都是随机访问迭代器.这两个位都支持您的问题的使用.(此外,Stroustrup显然在他最新的书中使用它;))

在C++ 11中进行此更改并非不太可能.我似乎记得为vector添加了相同的保证,它也获得了该版本非常有用的data()指针.

希望有所帮助.

  • 问题是pre-c ++ 11(它被标记为这样).你是对的,c ++ 11使得这样做是正式安全的. (2认同)