Skip to content

Add move assignment operator for Json::Value class and overload append member function for RValue references #635

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

Merged
merged 3 commits into from Jul 11, 2017

Conversation

ghost
Copy link

@ghost ghost commented Jul 8, 2017

TODO: add move assignment for CZString class also.

One problem is that I had to change the copy assignment from pass by value to pass by const reference because json_reader was giving errors of ambiguous overloads.
Though to make all tests pass I had to do a const_cast inside the assignment operator since I couldn't do a copy but rather a swap.

I don't like that and would like to fix this. But why is the swap necessary ? shouldn't it be a copy ?

@ghost
Copy link
Author

ghost commented Jul 8, 2017

should fix all things for #621

@ghost
Copy link
Author

ghost commented Jul 8, 2017

Well TODO completed too. Added move assignment for CZString also.

@cdunn2001 cdunn2001 merged commit 414b179 into open-source-parsers:master Jul 11, 2017
@cdunn2001
Copy link
Contributor

Thanks. I'll bump the minor version before the next release.

@cfyzium
Copy link

cfyzium commented Jul 25, 2017

I don't like that and would like to fix this. But why is the swap necessary ? shouldn't it be a copy ?

I believe it should be a copy. Moving/swapping objects on assignment is counterintuitive, especially so since argument of assignment operator is declared to be a const reference. It also breaks the code that relies on value semantics, e. g. working with containers. AFAIK it was one of the main reasons to remove auto_ptr.

@cdunn2001
Copy link
Contributor

@cfyzium, I'm mainly interested with maintaining backward-compatibility with this library. If we've altered behavior, please help us to fix it.

@cfyzium
Copy link

cfyzium commented Jul 31, 2017

@cdunn2001 yes, it clearly changes behavior. I've made pull request #640 to fix that.

Value::CZString& Value::CZString::operator=(CZString&& other) {
cstr_ = other.cstr_;
index_ = other.index_;
other.cstr_ = nullptr;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Accordingly to https://docs.microsoft.com/en-us/cpp/cpp/move-constructors-and-move-assignment-operators-cpp?view=vs-2019

  1. You should zero the original objects after moving the value.
  2. Check if you are not moving *this into *this.
   // Copy the data pointer and its length from the
   // source object.
   _data = other._data;
   _length = other._length;

   // Release the data pointer from the source object so that
   // the destructor does not free the memory multiple times.
   other._data = nullptr;
   other._length = 0;

...
   if (this != &other)

Copy link
Contributor

@BillyDonahue BillyDonahue Oct 7, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the link. I am a little skeptical of some sloppiness in the article, but it's fine for beginners I guess.

You don't have to zero everything. Only do enough work to make ~T and T::operator= valid and enforce your postconditions regarding the moved-from state of your class, which is up to you. Moved-from object's destructor and reassignment need to be correct, and maybe nothing else.

You don't have to do check against self-move and do nothing. You only have to anticipate that self-move-assign is possible and prove that it leaves the object in a safe moved-from state. Adding these checks without thinking about it can slow down the operation, just to support an outlier case.

All that said! CZString is not safe against self-move-assign. It will leak its allocation.
That's a for-real bug.

Value::CZString& Value::CZString::operator=(CZString&& other) {
  cstr_ = other.cstr_;
  index_ = other.index_;
  other.cstr_ = nullptr;  // cstr_ is leaked if this is self-move-assignment
  return *this;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants