为什么引用成员不引用嵌套向量上的赋值变量?声明访问 class 成员的替代方法的正确方法是什么?
Why don't reference members refer the assigned variable on nested vectors? What's a proper way to declare an alternative way to access a class member?
我想声明另一种访问 class 成员(特别是数组位置)的方法,如
class Foo {
int a[2];
int &a_first = a[0];
};
这样,在 Foo
实例中对 a_first
的任何访问在所有方面都等同于访问同一实例的 a[0]
。
上面的代码对 class 的单个实例和单个向量按预期工作,但是当用于嵌套向量时,引用地址与成员地址不同:
#include <iostream>
#include <vector>
class A {
public:
int m;
int &mref = m;
};
int main()
{
A a;
std::cout << (&a.m == &a.mref) << '\n'; // output: 1
std::vector<A> av1(1);
std::cout << (&av1[0].m == &av1[0].mref) << '\n'; // output: 1
std::vector<std::vector<A>> av2(1, std::vector<A>(1));
std::cout << (&av2[0][0].m == &av2[0][0].mref) << '\n'; // output: 0
return 0;
}
我认为引用变量充当其分配变量的别名,并且在编译时解析,而不在运行时分配任何实际内存,这与指针不同。为什么这与上面显示的行为不一致?实现我想要的别名的正确方法是什么?
The code above works as I expected
实际上不是:
class A {
public:
int m{};
int &mref = m;
};
int main()
{
A a;
A a2 = a;
std::cout << (&a2.m == &a2.mref) << '\n'; // output: 0
};
引用只能在初始化时绑定。复制将复制值,而不是重新绑定引用。因此,A
类型对象的任何副本都会弄乱您的引用。这就是您的嵌套向量示例中发生的情况。您不需要嵌套向量就可以看到这一点。尝试并推入 vector<A>
,矢量将不得不调整大小,并且在调整大小期间将复制其元素,从而弄乱您的参考。
I thought reference variables acted as aliases of their assigned variable ...
正确
... and were resolved at compile time without being assigned any actual memory at runtime, unlike pointers.
不总是。您不能总是在编译时解析引用,在这种情况下,引用实际上将在幕后用指针实现。
可能的解决方案:
使用 std::reference_wrapper
, the copy assignment operator 重新绑定引用,但您需要为您的 class:
实现自定义副本 constructor/assignments
class A {
public:
int m{};
std::reference_wrapper<int> mref = m;
A() = default;
A(const A& other) noexcept
: m{other.m},
mref{m}
{}
A& operator=(const A& other) noexcept
{
m = other.m;
mref = m;
return *this;
}
};
使用一种方法returns对变量的引用
class A {
public:
int m{};
int& mref() { return m; }
const int& mref() const { return m; }
};
我想声明另一种访问 class 成员(特别是数组位置)的方法,如
class Foo {
int a[2];
int &a_first = a[0];
};
这样,在 Foo
实例中对 a_first
的任何访问在所有方面都等同于访问同一实例的 a[0]
。
上面的代码对 class 的单个实例和单个向量按预期工作,但是当用于嵌套向量时,引用地址与成员地址不同:
#include <iostream>
#include <vector>
class A {
public:
int m;
int &mref = m;
};
int main()
{
A a;
std::cout << (&a.m == &a.mref) << '\n'; // output: 1
std::vector<A> av1(1);
std::cout << (&av1[0].m == &av1[0].mref) << '\n'; // output: 1
std::vector<std::vector<A>> av2(1, std::vector<A>(1));
std::cout << (&av2[0][0].m == &av2[0][0].mref) << '\n'; // output: 0
return 0;
}
我认为引用变量充当其分配变量的别名,并且在编译时解析,而不在运行时分配任何实际内存,这与指针不同。为什么这与上面显示的行为不一致?实现我想要的别名的正确方法是什么?
The code above works as I expected
实际上不是:
class A {
public:
int m{};
int &mref = m;
};
int main()
{
A a;
A a2 = a;
std::cout << (&a2.m == &a2.mref) << '\n'; // output: 0
};
引用只能在初始化时绑定。复制将复制值,而不是重新绑定引用。因此,A
类型对象的任何副本都会弄乱您的引用。这就是您的嵌套向量示例中发生的情况。您不需要嵌套向量就可以看到这一点。尝试并推入 vector<A>
,矢量将不得不调整大小,并且在调整大小期间将复制其元素,从而弄乱您的参考。
I thought reference variables acted as aliases of their assigned variable ...
正确
... and were resolved at compile time without being assigned any actual memory at runtime, unlike pointers.
不总是。您不能总是在编译时解析引用,在这种情况下,引用实际上将在幕后用指针实现。
可能的解决方案:
使用
实现自定义副本 constructor/assignmentsstd::reference_wrapper
, the copy assignment operator 重新绑定引用,但您需要为您的 class:class A { public: int m{}; std::reference_wrapper<int> mref = m; A() = default; A(const A& other) noexcept : m{other.m}, mref{m} {} A& operator=(const A& other) noexcept { m = other.m; mref = m; return *this; } };
使用一种方法returns对变量的引用
class A { public: int m{}; int& mref() { return m; } const int& mref() const { return m; } };