为什么对向量中 class 成员的引用指向不同对象的相同值?
why references to members of a class in a vector point to the same value for different objects?
来个简单的class:
class Var
{
public:
explicit Var(const std::string& name, const double v)
: value(v), ref(value), _name(name) {};
~Var() {};
double value{};
double& ref;
void print()
{
std::cout << _name << ":\n";
std::cout << "\tvalue = " << value << " (" << &value << ")\n";
std::cout << "\t ref = " << ref << " (" << &ref << ")\n\n";
}
private:
std::string _name;
};
在这种情况下一切正常:
Var v0("v0", 0.0);
Var v1("v1", 1.0);
Var v2("v2", 2.0);
v0.print();
v1.print();
v2.print();
输出为:
v0:
value = 0 (000000DDE3D3F878)
ref = 0 (000000DDE3D3F878)
v1:
value = 1 (000000DDE3D3F8E8)
ref = 1 (000000DDE3D3F8E8)
v2:
value = 2 (000000DDE3D3F958)
ref = 2 (000000DDE3D3F958)
但是当对象被放置在向量中时,ref 变量对于所有对象都是相同的。
vector<Var> V{};
for (size_t i = 0; i < 3; i++)
{
std::string name = "V[" + std::to_string(i) + "]";
V.push_back(Var(name, i));
}
for (size_t i = 0; i < 3; i++)
V[i].print();
输出:
V[0]:
value = 0 (000002B594F55C70)
ref = 2 (000000DDE3D3FA88)
V[1]:
value = 1 (000002B594F55CA8)
ref = 2 (000000DDE3D3FA88)
V[2]:
value = 2 (000002B594F55CE0)
ref = 2 (000000DDE3D3FA88)
我做错了什么?
块引用
std::vector
需要适当编写的赋值运算符。
编译器提供的那个对你的 class 没用,因为引用没有反弹。所以你需要自己写出来。这不是微不足道的:
Assignment operator with reference members
不过,最好的办法是删除参考 class 成员。
来个简单的class:
class Var
{
public:
explicit Var(const std::string& name, const double v)
: value(v), ref(value), _name(name) {};
~Var() {};
double value{};
double& ref;
void print()
{
std::cout << _name << ":\n";
std::cout << "\tvalue = " << value << " (" << &value << ")\n";
std::cout << "\t ref = " << ref << " (" << &ref << ")\n\n";
}
private:
std::string _name;
};
在这种情况下一切正常:
Var v0("v0", 0.0);
Var v1("v1", 1.0);
Var v2("v2", 2.0);
v0.print();
v1.print();
v2.print();
输出为:
v0:
value = 0 (000000DDE3D3F878)
ref = 0 (000000DDE3D3F878)
v1:
value = 1 (000000DDE3D3F8E8)
ref = 1 (000000DDE3D3F8E8)
v2:
value = 2 (000000DDE3D3F958)
ref = 2 (000000DDE3D3F958)
但是当对象被放置在向量中时,ref 变量对于所有对象都是相同的。
vector<Var> V{};
for (size_t i = 0; i < 3; i++)
{
std::string name = "V[" + std::to_string(i) + "]";
V.push_back(Var(name, i));
}
for (size_t i = 0; i < 3; i++)
V[i].print();
输出:
V[0]:
value = 0 (000002B594F55C70)
ref = 2 (000000DDE3D3FA88)
V[1]:
value = 1 (000002B594F55CA8)
ref = 2 (000000DDE3D3FA88)
V[2]:
value = 2 (000002B594F55CE0)
ref = 2 (000000DDE3D3FA88)
我做错了什么?
块引用
std::vector
需要适当编写的赋值运算符。
编译器提供的那个对你的 class 没用,因为引用没有反弹。所以你需要自己写出来。这不是微不足道的:
Assignment operator with reference members
不过,最好的办法是删除参考 class 成员。