BString: add support for move semantics with C++11 and up.

This implements the "rule of 5" for this type. While the copy operation for
BString was already using shallow copies of the underlying data, this change
further optimizes moving the data from one object to another.

While it is not the intention to implement move semantics to all types in the
legacy Haiku/Be kits, data types like BString are good candidates, because move
operations are often useful when working with data within an application.

In this implementation, the internal data of the string object will be set to
NULL, thus leaving an empty string.

Change-Id: I16bf9424f9b17f622b0b57659b80628e18760288
Reviewed-on: https://review.haiku-os.org/c/haiku/+/4428
Reviewed-by: Jérôme Duval <jerome.duval@gmail.com>
This commit is contained in:
Niels Sascha Reedijk 2021-09-06 15:37:30 +01:00 committed by Jérôme Duval
parent 3cf06bfc6b
commit 0b86520c4d
6 changed files with 88 additions and 4 deletions

View File

@ -2163,7 +2163,7 @@ INCLUDE_FILE_PATTERNS =
# recursively expanded use the := operator instead of the = operator.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
PREDEFINED = __cplusplus \
PREDEFINED = __cplusplus=201703L \
_SYS_TYPES_H \
__attribute__(x)=

View File

@ -40,7 +40,7 @@
strings. For all operations that perform on bytes, there is an equivalent
that operates on UTF-8 strings. See for example the BString::CopyInto() and
BString::CopyCharsInto() methods. The main difference is that if there are
any position argumens, the regular method counts the bytes and the
any position argumens, the regular method counts the bytes and the
Chars methods counts characters.
\since BeOS R5
@ -94,6 +94,21 @@
*/
#if __cplusplus >= 201103L
/*!
\fn BString::BString(BString&& string)
\brief Move the data from the \a string to this object.
Create a new string object with the data of another \a string. The
\a string will no longer point to the same contents.
\note This constructor is only available for modern C++ (C++11 or later).
\since Haiku R1
*/
#endif
/*!
\fn BString::~BString()
\brief Free all resources associated with the object.
@ -270,6 +285,22 @@
*/
#if __cplusplus >= 201103L
/*!
\fn BString& BString::operator=(BString&& string)
\brief Move the contents of \a string to this BString object.
The \a string will no longer point to the same contents.
\note This method is only available for modern C++ (C++11 or later).
\return This method always returns \c *this.
\since Haiku R1
*/
#endif
/*!
\fn BString& BString::SetTo(const char* str)
\brief Re-initialize the BString to a copy of the data of a string.

View File

@ -22,6 +22,9 @@ public:
BString(const char* string);
BString(const BString& string);
BString(const char* string, int32 maxLength);
#if __cplusplus >= 201103L
BString(BString&& string);
#endif
~BString();
// Access
@ -39,6 +42,9 @@ public:
BString& operator=(const BString& string);
BString& operator=(const char* string);
BString& operator=(char c);
#if __cplusplus >= 201103L
BString& operator=(BString&& string);
#endif
BString& SetTo(const char* string);
BString& SetTo(const char* string, int32 maxLength);

View File

@ -1,5 +1,5 @@
/*
* Copyright 2001-2014 Haiku, Inc. All rights reserved.
* Copyright 2001-2021 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
@ -193,6 +193,15 @@ BString::BString(const char* string, int32 maxLength)
}
#if __cplusplus >= 201103L
BString::BString(BString&& string)
{
fPrivateData = string.fPrivateData;
string.fPrivateData = NULL;
}
#endif
BString::~BString()
{
if (!_IsShareable() || atomic_add(&_ReferenceCount(), -1) == 1)
@ -263,6 +272,21 @@ BString::operator=(char c)
}
#if __cplusplus >= 201103L
BString&
BString::operator=(BString&& string)
{
if (this != &string) {
this->~BString();
// free up any resources allocated by the current contents
fPrivateData = string.fPrivateData;
string.fPrivateData = NULL;
}
return *this;
}
#endif
BString&
BString::SetTo(const char* string, int32 maxLength)
{

View File

@ -32,6 +32,17 @@ StringAssignTest::PerformTest(void)
CPPUNIT_ASSERT(strcmp(str->String(), "Something Else") == 0);
delete str;
// =(BString&&)
#if __cplusplus >= 201103L
NextSubTest();
BString movableString("Something movable");
str = new BString();
*str = std::move(movableString);
CPPUNIT_ASSERT(strcmp(str->String(), "Something movable") == 0);
CPPUNIT_ASSERT(strcmp(movableString.String(), "") == 0);
delete str;
#endif
// char ptr is NULL
NextSubTest();
char *s = NULL;

View File

@ -56,7 +56,19 @@ StringConstructionTest::PerformTest(void)
CPPUNIT_ASSERT(strncmp(string->String(), str, 5) == 0);
CPPUNIT_ASSERT(string->Length() == 5);
delete string;
// BString(BString&&)
#if __cplusplus >= 201103L
NextSubTest();
BString movableString(str);
string = new BString(std::move(movableString));
CPPUNIT_ASSERT(strcmp(string->String(), str) == 0);
CPPUNIT_ASSERT(string->Length() == strlen(str));
CPPUNIT_ASSERT(strcmp(movableString.String(), "") == 0);
CPPUNIT_ASSERT(movableString.Length() == 0);
delete string;
#endif
NextSubTest();
string = new BString(str, 255);
CPPUNIT_ASSERT(strcmp(string->String(), str) == 0);