class B
{
public:
B(int& a) :ref(a){}
B(B const&) = default;
int& ref;
};
void main()
{
int a1 = 1, a2 = 2;
B b1(a1), b2(b1), b3(a2);
b3 = b1;
}
如果编译器实现的隐式定义的复制赋值运算符是
B& operator=(const B& rhs)
{
this->ref = rhs.ref;
return *this;
}
为什么不能为引用生成?绑定到变量a的初始别名不受影响,因为在复制赋值运算符中,引用变量ref的数值会被更改。
答案 0 :(得分:1)
它可以做到,因为参考不能反弹到另一个。
如果编译器会生成一个像你提供的函数,我会这样做:
struct Ref {
int& num;
// hypotetical operator= generated
};
// ...
int a = 2;
int b = 5;
Ref ra{a};
Ref rb{b};
ra = rb; // now a = 5. Quite confusing.
a = 3; // still changes what value `ra.num` yeild. rb is not affected.
// will print "false".
std::cout << std::boolalpha << (ra.num == rb.num) << std::endl;
这会导致一些令人讨厌的错误。
我对此问题的首选解决方案是不在乎。我认为大多数用例并不是绝对必需的operator=
。
但是,如果您真的想为班级用户提供operator=
,则可以使用指针或std::reference_wrapper
代替参考。两者都允许您的类可分配,使您的引用可重新绑定。在这两者之间,我通常更喜欢指针,因为在我看来它们更容易使用。
struct Ref {
std::reference_wrapper<int> num;
};
// -- or --
struct Ref {
Ref(int& ref) : num{&ref} {}
int* num;
};
// ...
int a = 2;
int b = 5;
Ref ra{a};
Ref rb{b};
ra = rb; // now ra.num and rb.num are bound to the same reference.