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?
Asked
Active
Viewed 1,173 times
0
-
2Are 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
-
3Well 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 Answers
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;
- Returns: A pointer p such that p + i == &operator for each i in [0,size()].
- Complexity: constant time.
- 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()
.
-
2The `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