Is Std::String Ref-Counted in Gcc 4.X/C++11

Is std::string ref-counted in GCC 4.x / C++11?

Looking at libstdc++ documentation I find (see the link for more info):

A string looks like this:

                       [_Rep]
_M_length
[basic_string<char>] _M_capacity
_M_dataplus _M_refcount
_M_p ----------------> unnamed array of char_type

So, yes it is ref counted. Also, from the discussion here:

Yes, std::string will be made non-reference counting at some point,
but as a non-reference-counted string is valid in C++98 as well, one
option would be to switch to a non-ref-counted string for both
-std=c++98 and -std=c++11 modes. I'm not saying that's what will happen, but it could be.

So, it seems there are plans to change it to be conforming (I don't know how the progress is going though).

Update
As emsr points out in the comments, there is currently a non-reference counted extension called vstring.h, and it seems the only reason it hasn't replaced std::string is because of ABI compatibility. There is an SO question about it here.

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.

std::string copy constructor NOT deep in GCC 4.1.2?

It is entirely possible that your string implementation uses copy-on-write which would explain the behavior. Although this is less likely with newer implementations (and non-conforming on C++11 implementations).

The standard places no restriction on the value of the pointer returned by c_str (besides that it points to a null-terminated c-string), so your code is inherently non-portable.

Test whether libstdc++'s version uses a C++11-compliant std::string

The new C++11 compliant std::string was introduced with the new (dual) ABI in GCC 5 (Runtime Library Section of the changelog).

The macro _GLIBCXX_USE_CXX11_ABI decides whether the old or new ABI is being used, so just check it:

#if _GLIBCXX_USE_CXX11_ABI

Of course that's specific to libstdc++ only.

What is GCC's vstring ?

GCC's vstring is a versatile string class, which was introduced in GCC 4.1's libstdc++ implementation.

It is compatible with std::basic_string, with these additional details:

  • Two base classes are provided:

    • the default one avoids reference counting and is optimized for short strings;
    • the alternate one, still uses it (reference counting, that is) while improving in a few low level areas (e.g., alignment). See vstring_fwd.h for some useful typedefs.
  • Various algorithms have been rewritten (e.g., replace), the code streamlined and simple optimizations added.
  • Option 3 of DR 431 is implemented for both available bases, thus improving the support for stateful allocators.

DR431 is Library Working Group Defect Report 431, with option 3 looking like implementing better allocator support for the class to allow better swapping and other allocator-related operations.

The basic details are from GCC 4.1's release notes, under the Runtime Library section.

edit:

It looks as though the original purpose of this extension was to provide a basis for a C++11 std::string implementation. Paolo Carlini, a GCC/libstdc++ contributor, comments in this GCC Bug Report that <ext/vstring.h> contains a non-reference counted experimental version of the next std::string. Comment dated April 12, 2012:

What we tried to explain is that this sort of issue is well known and, more or
less, affects any reference counted implementation...
That is not the case when reference counting is not used and indeed it will not be
used (per the new C++11 Standard) in a new implementation of std::string which
we are currently showcasing as <ext/vstring.h>
...

C++11 internal std::string representation (libstdc++)

GCC did move away from the refcounted string to follow the c++11 standard, but note that it is possible that your program will use it as part of the ABI compatibility implementation.

How it is refcounted

std::string doesn't have a _Rep_Base member but a pointer to _Rep with _Rep inheriting from _Rep_Base

It is what is explained here :

 *  Where the _M_p points to the first character in the string, and
* you cast it to a pointer-to-_Rep and subtract 1 to get a
* pointer to the header.

The buffer lies after the header...

Yes, but after the header of the _Rep object, and your string only has a pointer to it.

C++11 std::promise returning std::string from thread, data pointer looks copied not moved

On promReceived.set_value(strObj);, string's copy constructor is called; not move constructor.

And although you use promReceived.set_value(std::move(strObj));, maybe there's no guarantee that data()'s return values are same.. As Mehrdad says, it can be different for each implementation, such as small string optimization.

(edit: And your implementation can be use copy constructor inside library..)

try to understand the pointers maintained by a string object

This actually depends on the version you're using. See, for example Is std::string refcounted in GCC 4.x / C++11?. When you write for two strings, a, and b

a = b;

Then there's a question of whether they're internally pointing to the same object (up until one of them is modified). So either behavior your program exhibits is not very surprising.



Related Topics



Leave a reply



Submit