0

While this may well be a stupid question, I saw something about how you shouldn't do this, despite the fact that it is allowed in C++ 11, but I don't quite get why. Could anyone explain why this is?

RT_34
  • 300
  • 2
  • 12
  • 2
    Are you referring to [this](http://stackoverflow.com/questions/14290795/why-is-modifying-a-string-through-a-retrieved-pointer-to-its-data-not-allowed)? – chris Feb 21 '13 at 22:42
  • 3
    Well it's `const` – is an immutable buffer useful to you? – ildjarn Feb 21 '13 at 22:43
  • It is **not** allowed in C++11. – juanchopanza Feb 21 '13 at 22:43
  • It might be confusing to someone who has to maintain the code. – Steve Wellens Feb 21 '13 at 22:43
  • 3
    @juanchopanza : Using `std::string` as a buffer is allowed in C++11, just by way of `&str[0]` rather than `str.c_str()`. – ildjarn Feb 21 '13 at 22:44
  • @ildjarn, As long as you don't overwrite the null character. – chris Feb 21 '13 at 22:44
  • @ildjarn the question is about using `std::string::c_str()` as a buffer. – juanchopanza Feb 21 '13 at 22:44
  • In response to those stating how it's const, and therefore unusable, it seems to work fine in several cases. @Chris, thanks for the article, that didn't come up for the searches. – RT_34 Feb 21 '13 at 22:44
  • 3
    @RT_34, Undefined behaviour seems to work fine in many cases. In a couple of months, it then doesn't. – chris Feb 21 '13 at 22:45
  • @chris : Right, the valid buffer range is `[0,s.size())`, just as with a `std::vector`. – ildjarn Feb 21 '13 at 22:45
  • OK, thanks, that makes sense. Because I prefer working with std::strings to C-style strings, is there any way to actually use a string as a buffer, for instance in Win32 SendMessage? – RT_34 Feb 21 '13 at 22:48
  • @RT_34, Yes, it's been mentioned: `&str[0]` and don't let it overwrite the null. – chris Feb 21 '13 at 22:49
  • But surely another null would be added from the message? EDIT: Ignore this, I just remembered something about how memory for stings is concurrent, and this would mess up. Therefore, I should defines string str[10], and call it via &str[0]? – RT_34 Feb 21 '13 at 22:50
  • @RT_34: What should add `0` to the string? How should the string know that it's interior has been changed? Therefore _you_ have the responsibility to keep the string valid if you use it as a `std::string` again. – Zeta Feb 21 '13 at 22:53
  • Just a personal preference, but for a buffer, I prefer `std::vector` to `std::string`. – James Kanze Feb 21 '13 at 23:08
  • @James : Of course if you eventually want the data in a `std::string`, that will involve copying all of the data, since one cannot transfer ownership of a `std::vector`'s buffer into a `std::string`. Fortunately this will become a non-issue once `string_ref` becomes standardized. – ildjarn Feb 21 '13 at 23:16
  • @ildjarn Good point, although if you're interfacing to legacy C code, it's probably that the function you're calling will do enough to make the time for the extra copy irrelevant. But I'll admit that my attitude may be out of date; when I started dealing with such problems, there was still active discussion about string implementations which didn't keep their data in a contiguous block. Now, of course... C++11 requires it (I think). – James Kanze Feb 21 '13 at 23:27

1 Answers1

6

It's not allowed!

21.4.7 basic_string string operations[string.ops]

21.4.7.1 basic_string accessors[string.accessors]

const charT* c_str() const noexcept;
const charT* data() const noexcept;
  1. Returns: A pointer p such that p + i == &operator for each i in [0,size()].
  2. Complexity: constant time.
  3. Requires: The program shall not alter any of the values stored in the character array.

Other than that, you're modifying data references by a const char *, which usually indicates a const_cast<char*>. Not only will this result in undefined behaviour, but according to Herb Sutter const should be read as thread-safe nowadays (see his talk about const and mutable).

However, as it has been stated, the use of std::string str; &str[0] is safe if str is sufficiently large. Just don't use .c_str() or .data().

Community
  • 1
  • 1
Zeta
  • 103,620
  • 13
  • 194
  • 236
  • 2
    The `const_cast` will cause undefined behavior only when a) casting away const-ness of an object that is const (rather than a reference that is const) and b) it is used to modify the object. The second part would be true, the first one depends on whether the string on which `c_str()` is called is const or not (and even if it is const, it might be that the buffer is still not const...). That being said, the better approach is using `&str[0]` – David Rodríguez - dribeas Feb 21 '13 at 23:00