Is It Legal to Write to Std::String

Is it legal to write to std::string?

std::string will be required to have contiguous storage with the new c++0x standard. Currently that is undefined behavior.

Legality of COW std::string implementation in C++11

It's not allowed, because as per the standard 21.4.1 p6, invalidation of iterators/references is only allowed for

— as an argument to any standard library function taking a reference
to non-const basic_string as an argument.

— Calling non-const
member functions, except operator[], at, front, back, begin, rbegin,
end, and rend.

For a COW string, calling non-const operator[] would require making a copy (and invalidating references), which is disallowed by the paragraph above. Hence, it's no longer legal to have a COW string in C++11.

Legal to overwrite std::string's null terminator?

LWG 2475 made this valid by editing the specification of operator[](size()) (inserted text in bold):

Otherwise, returns a reference to an object of type charT with value
charT(), where modifying the object to any value other than charT()
leads to undefined behavior.

Is it legal to modify the result of std::string::op[]?

The quote means that you cannot modify the return of operator[]( size() ), even if the value is well defined. That is, you must not modify the NUL terminator in the string even through the non-const overload.

This is basically your first option: i.e. pos >= size(), but because of the requirement pos <= size() the only possible value for that condition is pos == size().

The actual English description of the clause can be ambiguous (at least to me), but Appendix C, and in particular C.2.11 deals with changes in semantics in the string library, and there is no mention to this change --that would break user code. In C++03 the "referenced value shall not be modified" bit is not present and there is no ambiguity. The lack of mention in C.2.11 is not normative, but can be used as a hint that when they wrote the standard there was no intention on changing this particular behavior.

Is changing the std::string value through it's address is valid?

That is legal.

You are assigning a new value to the string but are using a pointer to refer to the original string; this is no more illegal then not using a pointer to refer to the original string i.e.

std::string foo = "foo";
foo = "bar";

// is pretty much the same thing as

std::string* foo_ptr = &foo;
*foo_ptr = "bar";

// which is what you are doing.

writing directly to std::string internal buffers

I'm not sure the standard guarantees that the data in a std::string is stored as a char*. The most portable way I can think of is to use a std::vector, which is guaranteed to store its data in a continuous chunk of memory:

std::vector<char> buffer(100);
FunctionInDLL(&buffer[0], buffer.size());
std::string stringToFillIn(&buffer[0]);

This will of course require the data to be copied twice, which is a bit inefficient.

Is writing to &str[0] buffer (of a std:string) well-defined behaviour in C++11?

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.

Is it safe to pass std::string to C style APIs?

If the C API function requires read-only access to the contents of the std::string then use the std::string::c_str() member function to pass the string. This is guaranteed to be a null terminated string.

If you intend to use the std::string as an out parameter, C++03 doesn't guarantee that the stored string is contiguous in memory, but C++11 does. With the latter it is OK to modify the string via operator[] as long as you don't modify the terminating NUL character.

Can you avoid using temporary buffers when using std::string to interact with C style APIs?

In C++11 you can simply pass a pointer to the first element of the string (&str[0]): its elements are guaranteed to be contiguous.

Previously, you can use .data() or .c_str() but the string is not mutable through these.

Otherwise, yes, you must perform a copy. But I wouldn't worry about this too much until profiling indicates that it's really an issue for you.



Related Topics



Leave a reply



Submit