33
char hello[] = "hello world";
std::string str;
str.resize(sizeof(hello)-1);
memcpy(&str[0], hello, sizeof(hello)-1);

This code is undefined behaviour in C++98. Is it legal in C++11?

Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
cubuspl42
  • 7,833
  • 4
  • 41
  • 65
  • 4
    The new guarantee of `std::string` buffer being contiguous. But I don't know if standard allows *writing* to that buffer, because as far as I know COW implementations of `std::string` are still possible. – cubuspl42 Aug 06 '14 at 20:52
  • 1
    why on earth would you want to do this? – user3791372 Aug 06 '14 at 20:54
  • 8
    @user3791372 So many good reasons. Example: `string str; str.resize(8); fread(&str[0], 1, str.size(), file);` – cubuspl42 Aug 06 '14 at 21:00
  • 11
    COW is not allowed in C++11. See this answer http://stackoverflow.com/questions/12199710/legality-of-cow-stdstring-implementation-in-c11 – imreal Aug 06 '14 at 21:10
  • So it seems to me that there is no reason for your code to be undefined behaviour. – imreal Aug 06 '14 at 21:11

1 Answers1

30

Yes, the code is legal in C++11 because the storage for std::string is guaranteed to be contiguous and your code avoids overwriting the terminating NULL character (or value initialized CharT).

From N3337, §21.4.5 [string.access]

 const_reference operator[](size_type pos) const;
 reference operator[](size_type pos);

1 Requires: pos <= size().
2 Returns: *(begin() + pos) if pos < size(). Otherwise, returns a reference to an object of type charT with value charT(), where modifying the object leads to undefined behavior.

Your example satisfies the requirements stated above, so the behavior is well defined.

Praetorian
  • 106,671
  • 19
  • 240
  • 328
  • How long is the reference returned by #2 required to be valid for? Is the reference required to refer to the contiguous storage? That is to say, could a conforming implementation return reference to a `char` that is a copy of the requested location provided that reads and writes of it (and it alone) are as expected? – BCS Oct 20 '14 at 13:36
  • 1
    @BCS The reference would be valid for the lifetime of the string, or until you do something that invalidates references (and iterators), usually resizing the string. In addition to the section quoted above, also refer to *[string.accessors]* for the description of the `data()` member function. Between the two, it'll be clear that a conforming implementation needs to have contiguous storage, and `operator[]` returns a reference to an element within this storage. – Praetorian Oct 20 '14 at 14:32