1

Consider a class with just a single member for this example.

class tester
{
public:
    int tester_value;

    tester(){}

    tester(int test_val)
    {
      tester_value = test_val;
    } 
    

    tester(const tester & data) : tester_value(data.tester_value)
    {
      std::cout << "Copied!" << std::endl;
    }
};

I was curious as to the proper way to overload the = operator and why one way works and another does not.

For example, this operator overload does not seem to properly copy the data from one object to another.

Example 1:

tester operator=(const tester & data) const
{
  tester temp;    
  std::memcpy(&temp, &data, sizeof(tester));
  return temp;
}

However, this example works just fine.

Example 2:

tester& operator=(const tester & data)
{        
  tester_value = data.tester_value;

  return *this;
}

When using the following code to test each example...

  tester my_test = tester(15);
  
  tester my_second_test = tester(20);    
  
  my_test = my_second_test;
  
  std::cout << "my_test.tester_value:" << my_test.tester_value << std::endl;
  
  std::cout << "my_second_test.tester_value:" << my_second_test.tester_value << std::endl;

The result for example 1 will be:

15
20

While the result for example 2 will be:

20
20

So,

Question 1: Why is it that using a temporary variable and memcpy() does not work properly to copy the data from one object to another when overloading the = operator?

Question 2: What is the proper and most efficient way to do overload this operator?

I appreciate any explanation, I am still getting used to the C++ language.

Thanks in advance!

  • 1
    With a simple class like this one `memcpy` shouldn't be harmful, but it's vast overkill and with a more complicated class it would be fatal. In C++ you should keep `memcpy` in the toolbox until you have a very good reason to take it out an use it. – user4581301 Aug 24 '22 at 23:04
  • 1
    Does this answer your question? [What are the basic rules and idioms for operator overloading?](https://stackoverflow.com/questions/4421706/what-are-the-basic-rules-and-idioms-for-operator-overloading) – Richard Critten Aug 24 '22 at 23:04
  • 1
    It's very weird for `operator=` to be `const`. The whole point is that you're changing the left hand side of the `=` by assigning something to it. – Nathan Pierson Aug 24 '22 at 23:12
  • 1
    Your example 1 is flawed. Don't use `std::memcpy()` on instances of non-trivial classes (common cases of this include a class with any virtual functions or one with a hand-rolled assignment operator. constructor, or destructor) since behaviour is undefined. It is usually advisable that `operator=()` return a reference, not by value. – Peter Aug 25 '22 at 01:22
  • Each of these comments provide a wonderful insight into this problem and very useful tips on C++ programming techniques and paradigms as a whole. I really appreciate all of the help! – EmbeddedDOOD Aug 25 '22 at 15:42

1 Answers1

2

Question 1: Why is it that using a temporary variable and memcpy() does not work properly to copy the data from one object to another?

This is because of the Golden Rule Of Computer Programming: "Your computer always does exactly what you tell it to do, instead of what you want it to do".

Tester A, B;

// ... at some point later.

A=B;

The instruction A=B instructs your computer to invoke A's operator= overload. In the overload, *this becomes A.

tester operator=(const tester & data) const
{
  tester temp;    
  std::memcpy(&temp, &data, sizeof(tester));
  return temp;
}

Nothing here tells your computer that anything in *this gets modified. Since you did not tell your computer to modify this->tester_value it does not get modified.

Nothing here effectively sets A.tester_value. Instead, some new object gets created and returned. That's what you told your computer to do, so that's what it does, no more no less. But the return value is not used for anything. The return value here is the value for the entire A=B; statement itself, which is not used for anything. It is the operator= itself that's responsible for assigning the new value of this object. It is not the return value from the operator= method that sets the new value of the object, it's the operator itself. In the operator= overload, what's on the right side of the = in the expression gets passed to operator= as a parameter, and what's on the left side of the = in the expression is *this.

Question 2: What is the proper and most efficient way to do overload this operator?

That's already answered by Stackoverflow's canonical on operating overloading. TLDR: it's "Example 2".

Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148
  • 1
    Addendum: The trailing `const` promises (enforced by the compiler) that the method will not modify (or allow to be modified) the instance on which the method is invoked. This is nonsensical for an assignment operator because the entire point of an assignment operator is to modify the instance. – user4581301 Aug 24 '22 at 23:28
  • Thank you so much for the detailed explanation! This makes a lot of sense. – EmbeddedDOOD Aug 25 '22 at 15:25