Compound assignment and add operator overloading

user1363061 picture user1363061 · Apr 30, 2012 · Viewed 11.4k times · Source

I need help with both of my operator overloading functions presented below. I'm unsure of how I can implement this without actually using the assignment in the function definitions.

Code for operator + in my .cpp file:

MyString& MyString::operator +(const MyString& rhs)
{
  delete [] String;
  String = new char[rhs.Size];
  Size = rhs.Size;
  // needs to be a loop for cascading + 
  // so that String1=String2+String3+String4 will work
  for(int i = 0; i < rhs.Size+1 ; i++)
  {
    //  String[i] + rhs.String[i]; ???
  }
  return *this;
}

Code for += operator in .cpp file:

MyString& MyString::operator+=(const MyString& rhs)
{
  delete [] String;
  String = new char[rhs.Size];
  String = String + rhs.String;
  return *this;
}

Call from main.cpp:

 String1 = String2 + String3 + String4;
 String1.Print ();

 String2 += String3;
 String2.Print ();

I know my .cpp file codes are wrong, some insight would be great!

Answer

David Rodr&#237;guez - dribeas picture David Rodríguez - dribeas · Apr 30, 2012

The idiomatic way is to implement the functionality in operator+= and then use that to implement operator+. Assume for starters than your operator+= is correctly implemented, then operator+ is trivially implementable as a free function:

MyString operator+( MyString lhs, MyString const & rhs ) {
   lhs += rhs;
   return lhs;
}

Note: The first argument is passed by value, so that it is a copy of the original that we can modify through operator+=. There are some other tips you might find useful here.

Now back to implementing operator+=, the first thing that you should understand is what the operations that you need to perform are: you need to allocate a longer buffer, copy from the old buffer, append the rhs string, swap the old buffer and the new (which contains the result) and free the old buffer. The order of the operations is important, if you release the old contents before copying (as you are doing) then you can no longer copy from that.

// Rough approach
MyString& operator+=( MyString const & rhs ) {
   char * new_buffer = new char[ Size + rhs.size + 1];       // [1]
   std::copy_n( String, Size, new_buffer );
   std::copy_n( rhs.String, rhs.Size + 1, new_buffer+Size ); // [2]
   swap(String, new_buffer);                                 // [3]
   Size = Size + rhs.Size;
   delete [] new_buffer;
   return *this;
}

[1]: Allocate the new buffer and copy to it. Note that in this particular case the code is correct because none of the rest of the instructions in the function can throw an exception. If that was not the case, the new buffer should be managed through RAII to ensure at least the minimal exception safety.

[2]: Assumes that as an invariant of the type MyString there is always a null terminator. The Size+1 in the count argument will copy all elements and the null terminator.

[3]: At this point all the operations have been performed, we can exchange the old and new buffers, update the size and release new_buffer (that actually refers to the old buffer)