【问题标题】:C++ copy assignment operator behaviourC++ 复制赋值运算符行为
【发布时间】:2022-01-18 15:11:18
【问题描述】:

我使用下面的代码来测试复制赋值运算符的行为:

#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;
}

我希望 p1 和 p2 具有相同的值 stamina。但是输出显示p2的stamina和p1的不一样

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

为什么复制赋值运算符不将 p1 的 stamina 的值复制到 p2?

【问题讨论】:

  • 您已经定义了一个用户定义的赋值运算符,您在其中明确地复制stamina。所以根据定义,这是行不通的。如果那是您需要的,只需复制耐力即可。
  • 您的代码有未定义的行为。只需在复制赋值运算符中添加stamina = rhs.stamina;,您就会得到预期的输出。
  • 但为什么 group 被复制而 stamina 没有?
  • 你有什么证据表明group被复制了?您的代码没有复制它。简单地说,它被初始化为相同的值(或作为相同整数变量的 const ref)并且复制运算符没有更改它。无论如何,group 被声明为 const ref,您无法更改它...
  • 在相关的注释中,引用是非常糟糕的成员。在此代码之后为group_number 分配一个新值,然后再次检查这两个对象。

标签: c++ class assignment-operator copy-assignment explicit-constructor


【解决方案1】:

您没有在复制赋值运算符中复制数据成员stamina。因此,只需在复制赋值运算符中添加stamina = rhs.stamina;,您就会得到预期的输出。所以修改后的operator= 定义如下:

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

另外,请注意,在您的原始代码 sn-p 中,由于数据成员 stamina 未初始化,因此它具有不确定值。使用这个未初始化的变量(你在写 p2.get_stamina(); 时所做的)是未定义的行为

未定义的行为表示任何1都可能发生包括但不限于程序提供您预期的输出。但是永远不要依赖(或根据)具有未定义行为的程序的输出。

因此,您看到的输出是未定义行为的结果。正如我所说,不要依赖具有 UB 的程序的输出

因此,使程序正确的第一步是删除 UB。 只有这样你才能开始推理程序的输出。

解决这个更严重的问题,只需对数据成员 stamina 使用 in-class initilaizer

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

1有关未定义行为的更准确的技术定义,请参阅this,其中提到:对程序的行为没有限制 .

【讨论】:

    【解决方案2】:

    为什么复制赋值运算符不将p1的stamina值复制到p2?

    您定义了运算符。您不会在运算符的定义中复制任何值,因此不会复制任何值。

    您可以这样分配成员:

    stamina = rhs.stamina;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-11-21
      • 2020-11-18
      • 1970-01-01
      • 2015-12-13
      • 1970-01-01
      • 2013-10-26
      • 2016-05-18
      • 2019-11-17
      相关资源
      最近更新 更多