-
-
Notifications
You must be signed in to change notification settings - Fork 7k
Fix move constructor and operator= in String. #6261
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -43,16 +43,15 @@ String::String(const __FlashStringHelper *pstr) | |
*this = pstr; | ||
} | ||
|
||
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) | ||
#if STRING_HAS_MOVE | ||
String::String(String &&rval) | ||
: buffer(rval.buffer) | ||
, capacity(rval.capacity) | ||
, len(rval.len) | ||
{ | ||
init(); | ||
move(rval); | ||
} | ||
String::String(StringSumHelper &&rval) | ||
{ | ||
init(); | ||
move(rval); | ||
rval.buffer = NULL; | ||
rval.capacity = 0; | ||
rval.len = 0; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No need for these last two lines - all that matters is that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. According to c++ standard, object needs to be in valid state after being moved from. Having null buffer and non-zero capacity and /or length does not seem like a valid state to me. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Keep the state sane is probably a good idea, so I'd suggest leaving these in. |
||
} | ||
#endif | ||
|
||
|
@@ -189,25 +188,22 @@ String & String::copy(const __FlashStringHelper *pstr, unsigned int length) | |
return *this; | ||
} | ||
|
||
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) | ||
#if STRING_HAS_MOVE | ||
void String::move(String &rhs) | ||
{ | ||
if (buffer) { | ||
if (rhs && capacity >= rhs.len) { | ||
strcpy(buffer, rhs.buffer); | ||
len = rhs.len; | ||
rhs.len = 0; | ||
return; | ||
} else { | ||
if (this != &rhs) | ||
{ | ||
if (buffer != NULL) | ||
free(buffer); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. FYI: The There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks. Removed the null checks before free. |
||
} | ||
|
||
buffer = rhs.buffer; | ||
len = rhs.len; | ||
capacity = rhs.capacity; | ||
|
||
rhs.buffer = NULL; | ||
rhs.len = 0; | ||
rhs.capacity = 0; | ||
} | ||
buffer = rhs.buffer; | ||
capacity = rhs.capacity; | ||
len = rhs.len; | ||
rhs.buffer = NULL; | ||
rhs.capacity = 0; | ||
rhs.len = 0; | ||
} | ||
#endif | ||
|
||
|
@@ -221,16 +217,10 @@ String & String::operator = (const String &rhs) | |
return *this; | ||
} | ||
|
||
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) | ||
#if STRING_HAS_MOVE | ||
String & String::operator = (String &&rval) | ||
{ | ||
if (this != &rval) move(rval); | ||
return *this; | ||
} | ||
|
||
String & String::operator = (StringSumHelper &&rval) | ||
{ | ||
if (this != &rval) move(rval); | ||
move(rval); | ||
return *this; | ||
} | ||
#endif | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really these should all have a call to
std::move
, but of coursestd::move
is not available on the arduino.Perhaps it would be sensible to provide
std::move
andstd::forward
if arduino is going to start using rvalue references internallyThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Even if std::move was available it would not make much sense to use it here - all it does is to cast is argument to rvalue reference. For integral types and pointers move construction is same as copy construction.
I agree that it would be useful to have move and forward available in lib.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess having
std::move
on all these assignments would allow move semantics / optimizations on each of the fields, but since we know these are just a pointer and two integers, it should not make any difference here. So I guess the code is good as the PR proposes it.