C++ 复制赋值运算符行为
C++ copy assignment operator behaviour
我使用下面的代码来测试复制赋值运算符的行为:
#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?
Why the copy assignment operator not copying the value of p1's stamina to p2?
您定义了运算符。您没有在运算符的定义中复制任何值,因此不会复制任何值。
您可以这样分配成员:
stamina = rhs.stamina;
您没有在复制赋值运算符中复制数据成员stamina
。因此,只需在复制赋值运算符中添加 stamina = rhs.stamina;
即可获得预期的输出。所以 operator=
的修改定义看起来像:
Player& operator=(const Player& rhs)
{
cout << "Copy assignment operator called " << endl;
stamina = rhs.stamina; //ADDED THIS
return *this;
}
另外请注意,在您的原始代码片段中,由于数据成员 stamina
未初始化,因此它具有 不确定值 。使用这个未初始化的变量(你在写 p2.get_stamina();
时所做的)是 未定义的行为。
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.
所以您看到的输出是未定义行为的结果。正如我所说,不要依赖具有 UB 的程序的输出。
因此,使程序正确的第一步是删除 UB。 然后并且只有那时你可以开始对程序的输出进行推理。
为了解决这个更严重的问题只需对数据成员stamina
使用in-class initilaizer。
class Player {
//other members here
private:
int stamina = 0; //USE IN-CLASS INITIALIZER
};
1有关未定义行为的技术上更准确的定义,请参阅 this 其中提到:没有对程序行为的限制.
我使用下面的代码来测试复制赋值运算符的行为:
#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?
Why the copy assignment operator not copying the value of p1's stamina to p2?
您定义了运算符。您没有在运算符的定义中复制任何值,因此不会复制任何值。
您可以这样分配成员:
stamina = rhs.stamina;
您没有在复制赋值运算符中复制数据成员stamina
。因此,只需在复制赋值运算符中添加 stamina = rhs.stamina;
即可获得预期的输出。所以 operator=
的修改定义看起来像:
Player& operator=(const Player& rhs)
{
cout << "Copy assignment operator called " << endl;
stamina = rhs.stamina; //ADDED THIS
return *this;
}
另外请注意,在您的原始代码片段中,由于数据成员 stamina
未初始化,因此它具有 不确定值 。使用这个未初始化的变量(你在写 p2.get_stamina();
时所做的)是 未定义的行为。
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.
所以您看到的输出是未定义行为的结果。正如我所说,不要依赖具有 UB 的程序的输出。
因此,使程序正确的第一步是删除 UB。 然后并且只有那时你可以开始对程序的输出进行推理。
为了解决这个更严重的问题只需对数据成员stamina
使用in-class initilaizer。
class Player {
//other members here
private:
int stamina = 0; //USE IN-CLASS INITIALIZER
};
1有关未定义行为的技术上更准确的定义,请参阅 this 其中提到:没有对程序行为的限制.