Given that:
1) The C++03 standard does not address the existence of threads in any way
2) The C++03 standard leaves it up to implementations to decide whethe
You are right. This will be fixed in C++0x. For now you have to rely on your implementation's documentation. For example, recent libstdc++ Versions (GCC) lets you use string objects as if no string object shares its buffer with another one. C++0x forces a library implemetation to protect the user from "hidden sharing".
A more correct way to look at it would be "You cannot safely and portably use C++ in a multithreaded environment". There is no guarantee that other data structures will behave sensibly either. Or that the runtime won't blow up your computer. The standard doesn't guarantee anything about threads.
So to do anything with threads in C++, you have to rely on implementation-defined guarantees. And Then you can safely use std::string
because each implementation tells you whether or not it is safe to use in a threaded environment.
You lost all hope of true portability the moment you spawned a second thread. std::string
isn't "less portable" than the rest of the language/library.
You can use STLport. It provides non-COW strings. And it has the same behavior on different platforms.
This article presents comparison of STL strings with copy-on-write and noncopy- on-write argorithms, based on STLport strings, ropes and GNU libstdc++ implementations.
In a company where I work I have some experience running the same server application built with STLport and without STLport on HP-UX 11.31. The application was compiled with gcc 4.3.1 with optimization level O2. So when I run the progrma built with STLport it processes requests 25% faster comparing to the the same program built without STLport (which uses gcc own STL library).
I profiled both versions and found out that the version without STLport spends much more time in pthread_mutex_unlock()
(2.5%) comparing to the version with STLport (1%). And pthread_mutex_unlock()
itself in the version without STLport is called from one of std::string functions.
However, when after profiling I changed assignments to strings in most often called functions in this way:
string_var = string_var.c_str(); // added .c_str()
there was significant improvement in performance of the version without STLport.
Given that the standard doesn't say a word about memory models and is completely thread unaware, I'd say you can't definitely assume every implementation will be non-cow so no, you can't
Apart from that, if you know your tools, most of the implementations will use non-cow strings to allow multi-threading.
In MSVC, std::string is no longer reference counted shared pointer to a container. They choose to the entire contents by-value in every copy constructor and assignment operator, to avoid multithreading problems.
If you want to disable COW semantics, you could force your strings to make copies:
// instead of:
string newString = oldString;
// do this:
string newString = oldString.c_str();
As pointed out, especially if you could have embedded nulls, then you should use the iterator ctor:
string newString(oldString.begin(), oldString.end());