隐式定义的复制赋值运算符

时间:2016-11-23 21:18:01

标签: c++

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的数值会被更改。

1 个答案:

答案 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.