I know that in C++03, technically the std::basic_string
template is not required to have contiguous memory. However, I'm curious how many implementations exist for modern compilers that actually take advantage of this freedom. For example, if one wants to use basic_string
to receive the results of some C API (like the example below), it seems silly to allocate a vector just to turn it into a string immediately.
Example:
DWORD valueLength = 0;
DWORD type;
LONG errorCheck = RegQueryValueExW(
hWin32,
value.c_str(),
NULL,
&type,
NULL,
&valueLength);
if (errorCheck != ERROR_SUCCESS)
WindowsApiException::Throw(errorCheck);
else if (valueLength == 0)
return std::wstring();
std::wstring buffer;
do
{
buffer.resize(valueLength/sizeof(wchar_t));
errorCheck = RegQueryValueExW(
hWin32,
value.c_str(),
NULL,
&type,
&buffer[0],
&valueLength);
} while (errorCheck == ERROR_MORE_DATA);
if (errorCheck != ERROR_SUCCESS)
WindowsApiException::Throw(errorCheck);
return buffer;
I know code like this might slightly reduce portability because it implies that std::wstring
is contiguous -- but I'm wondering just how unportable that makes this code. Put another way, how may compilers actually take advantage of the freedom having noncontiguous memory allows?
EDIT: I updated this question to mention C++03. Readers should note that when targeting C++11, the standard now requires that basic_string
be contiguous, so the above question is a non issue when targeting that standard.
A std::string's allocation is not guaranteed to be contiguous under the C++98/03 standard, but C++11 forces it to be. In practice, neither I nor Herb Sutter know of an implementation that does not use contiguous storage.
It's stored with a size. If you store a new string, it will optionally deallocate the existing memory and allocate new memory to cope with the change in size. And it doesn't necessarily allocate 4 bytes the first time you assign a string of 4 bytes to it. It may allocate more space than that (it won't allocate less).
I'd consider it quite safe to assume that std::string allocates its storage contiguously.
At the present time, all known implementations of std::string
allocate space contiguously.
Moreover, the current draft of C++ 0x (N3000) [Edit: Warning, direct link to large PDF] requires that the space be allocated contiguously (§21.4.1/5):
The char-like objects in a basic_string object shall be stored contiguously. That is, for any basic_string object s, the identity &*(s.begin() + n) == &*s.begin() + n shall hold for all values of n such that 0 <= n < s.size().
As such, the chances of a current or future implementation of std::string
using non-contiguous storage are essentially nil.
A while back there was a question about being able to write to the storage for a std::string
as if it were an array of characters, and it hinged on whether the contents of a std::string
were contiguous:
My answer indicated that according to a couple well regarded sources (Herb Sutter and Matt Austern) the current C++ standard does require std::string
to store its data contiguous under certain conditions (once you call str[0]
assuming str
is a std::string
) and that that fact pretty much forces the hand of any implementation.
Basically, if you combine the promises made by string::data()
and string::operator[]()
you conclude that &str[0]
needs to return a contiguous buffer. Therefore Austern suggests that the committee just make that explicit, and apparently that's what'll happen in the 0x standard (or are they calling it the 1x standard now?).
So strictly speaking an implementation doesn't have to implement std::string
using contiguous storage, but it has to do so pretty much on demand. And your example code does just that by passing in &buffer[0]
.
Links:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With