隐式定义的副本分配运算符

Implicitly-defined copy assignment operator

本文关键字:分配 运算符 副本 定义      更新时间:2023-10-16
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的数字值已更改。

它可以做到这一点,因为参考不能反弹到另一个。

如果编译器会像您提供的那样生成一个函数,我会这样做:

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.