BasicString
BasicString is a template class implementing a reference counted C++ string type.
The API is similar to the API exposed by std::basic_string, and it’s used throughout
the Harlinn.Common.Core library
as a container for sequences of the char or wchar_t character types.
The internal representation of the string data is:
template< typename T >
struct Data
{
using CharType = T;
size_t referenceCount_ = 1;
size_t size_ = 0;
CharType buffer_[1024];
size_t AddRef( ) noexcept
{
return InterlockedIncrementSizeT( &referenceCount_ );
}
size_t DecRef( ) noexcept
{
return InterlockedDecrementSizeT( &referenceCount_ );
}
};
The above specifies the layout of the string data, which is basically
| Member | Size |
|---|---|
| Reference count | 8 bytes |
| Number of characters | 8 bytes |
| The first character | sizeof(CharType) |
| The second character | sizeof(CharType) |
| . | . |
| . | . |
The size_th character |
sizeof(CharType) |
| Terminating zero | sizeof(CharType) |
The buffer size doesn’t really mean anything, it could be set to 1 and it would change nothing.
Setting it to something quite a bit larger is just convenient for debugging purposes, and nothing else.
The BasicString template has a single
data member, Data* data_, so the the size of a BasicString
object is just the size of this pointer.
A BasicString of length 0
does have a data object, so initializing a container with a large number of empty BasicString
objects is cheap, and so is copying the contents of the BasicString
object, as no allocation will occur, since all that is needed is incrementing the reference count.
BasicString( const BasicString& other ) noexcept
: data_( other.data_ )
{
if ( data_ )
{
data_->AddRef( );
}
}
BasicString can be move constructed:
BasicString( BasicString&& other ) noexcept
: data_( other.data_ )
{
other.data_ = nullptr;
}
and move assigned:
BasicString& operator = ( BasicString&& other ) noexcept
{
std::swap( other.data_, data_ );
return *this;
}
BasicString objects are not thread safe,
but BasicString objects on different threads can
share the same reference counted Data object.