-1

I used the code below to test the behaviour of copy assignment operator:

#include <iostream>
using namespace std;

int group_number = 10; // Global

class Player {
public:
  explicit Player(const int &g): group(g)
  {
  }

  Player& operator=(const Player& rhs)
  {
      cout << "Copy assignment operator called " << endl;
      return *this;
  }

  void set_stamina(int i) {stamina = i; }
  int  get_stamina()      {return stamina; }
  const int &get_group()  const { return group; }

protected:
  const int &group;

private:
  int stamina;
}; // End of Player class

class Round {
public:
  Round(const Player &p)
  {
    main_player = &p;
  }

  const Player &get_main_player() const
  {
    return *main_player;
  }

protected:
  const Player *main_player;
}; // End of Round class

// Test code
int main()
{
  Player p1(group_number);
  Round r(p1);
  p1.set_stamina(100);

  // Add player2 in the same group as p1
  Player p2(group_number);
  p2 = r.get_main_player();
  cout << "This is p1's stamina: "    << p1.get_stamina()
       << ", and p1's group number: " << p1.get_group() << endl;;
  cout << "This is p2's stamina: "    << p2.get_stamina()
       << ", and p2's group number: " << p2.get_group() << endl;;

  return 0;
}

I expected both p1 and p2 have the same value of stamina. But the output shows that p2's stamina is different from p1's

Copy assignment operator called
This is p1's stamina: 100, and p1's group number: 10
This is p2's stamina: 241098768, and p2's group number: 10

Why the copy assignment operator not copying the value of p1's stamina to p2?

ZR_xdhp
  • 361
  • 2
  • 13
  • 7
    You've defined a user defined assignment operator in which you explicitely do _not_ copy the stamina. So by definition this wont work. Just copy over the stamina if thats what you require. – Mike Vine Jan 18 '22 at 15:16
  • Your code has **undefined behavior**. Just add `stamina = rhs.stamina;` inside the copy assignment operator and you'll get your expected output. – Jason Jan 18 '22 at 15:21
  • but why `group` gets copied but `stamina` not? – ZR_xdhp Jan 18 '22 at 15:25
  • _"but why group gets copied but stamina not?"_ What makes you think group gets copied? – Drew Dormann Jan 18 '22 at 15:26
  • What exactly makes you think `group` is copied? Do you have any evidence that its value has changed? – n. m. could be an AI Jan 18 '22 at 15:28
  • 1
    What evidence do you have that `group` was copied? Your code did not copy it. Simply it was initialized to the same value (or as a const ref to the same integer variable) and the copy operator did not change it. Anyway as `group` is declared as a const ref, you cannot change it... – Serge Ballesta Jan 18 '22 at 15:28
  • 1
    On a related note, references make very bad members. Assign a new value to `group_number` after this code, then examine both objects again. – molbdnilo Jan 18 '22 at 15:33
  • @SergeBallesta Thanks for the explanation. The output makes me think that group got copied but stamina not. Appearantly it was not. – ZR_xdhp Jan 18 '22 at 15:41

2 Answers2

2

You have not copied the data member stamina inside the copy assignment operator. So just add stamina = rhs.stamina; inside the copy assignment operator and you'll get your expected output. So the modified definition of operator= looks like:

Player& operator=(const Player& rhs)
  {
      cout << "Copy assignment operator called " << endl;
      stamina = rhs.stamina; //ADDED THIS 
      return *this;
  }

Also, note that in your original code snippet, since the data member stamina is not initilized and so it has indeterminate value. Using this uninitialized variable(which you do when you wrote p2.get_stamina();) is undefined behavior.

Undefined behavior means anything1 can happen including but not limited to the program giving your expected output. But never rely(or make conclusions based) on the output of a program that has undefined behavior.

So the output that you're seeing is a result of undefined behavior. And as i said don't rely on the output of a program that has UB.

So the first step to make the program correct would be to remove UB. Then and only then you can start reasoning about the output of the program.

To solve this more serious problem just use in-class initilaizer for data member stamina.

class Player {
    //other members here
private:
  int stamina = 0; //USE IN-CLASS INITIALIZER
};

1For a more technically accurate definition of undefined behavior see this where it is mentioned that: there are no restrictions on the behavior of the program.

Jason
  • 36,170
  • 5
  • 26
  • 60
1

Why the copy assignment operator not copying the value of p1's stamina to p2?

You defined the operator. You don't copy any values in your definition of the operator, so no values are being copied.

You could assign the member like this:

stamina = rhs.stamina;
eerorika
  • 232,697
  • 12
  • 197
  • 326