Когда мы должны сделать оператор присваивания приватным и не реализовывать

Это старый экзаменационный вопрос, который просит нас писать операторы присваивания и копировать конструкторы, деструкторы, когда это имеет смысл.

Учитывая следующий код:

class U { /* code not specified here */ };
class A { /* code not specified here */ private: U& u_; };

Я узнал, что Ответ таков: A содержит ссылку C++ на экземпляр U, который можно скопировать, но нельзя сбросить. Поэтому вы должны:

• Написать конструктор копирования, который инициализирует свой U тому же экземпляру, на который ссылается исходный экземпляр A.

• Сделайте свой оператор присваивания частным и не реализуйте

Я знаю, что ссылка не может быть сброшена. Однако означает ли это, что я никогда не смогу использовать оператор присваивания, когда класс содержит данные ссылочного члена? Имеет ли смысл следующий код? Следующий код написан мной (это не ответ)

  class U{
    public:
        int u;
    };

    class A{
    public:
        A(U& u):u_(u){}
        A& operator=(const A& a){
            u_ = a.u_;
            return *this;
        }
        U& u_;
    };

    int main(){
        U u1;
        U u2;
        A a1(u1);
        A a2(u2);
        a1 = a2;
        a1.u_.u = 1;
        a2.u_.u = 2;
        cout << "a1.u_.u : " << a1.u_.u << endl;
        cout << "a2.u_.u : " <<  a2.u_.u << endl;
    }

Заранее спасибо.

5 ответов

A& operator=(const A& a){
    u_ = a.u_;
    return *this;
}

Не будет работать, как ожидалось, U контрольные точки будут назначены.
Конечно, вы можете реализовать оператор присваивания, даже если класс содержит ссылку, при условии, что эта ссылка может быть назначена (что, если указанный класс имеет operator= только приват?) а ссылка не const U& (таким образом, не может быть назначен).

Ссылки не могут быть изменены, чтобы ссылаться на что-то еще. Однако вы можете делать то, что вы делаете здесь, потому что делаете:

u_ = a.u_;

в действительности изменяется значение, на которое ссылаются. Он отмечает изменение, на которое ссылается значение.

Означает ли это, что я никогда не смогу использовать оператор присваивания, когда класс содержит данные ссылочного члена?

У вас может быть оператор присваивания, вы просто не можете переназначить ссылку и, следовательно, должны переопределить ожидаемое поведение оператора присваивания.

Ссылки можно рассматривать как указатели. Единственное отличие состоит в том, что вы не можете изменить место, на которое указывает ссылка, после того, как она была назначена. В вашем операторе присваивания вы копируете содержимое ссылок, а не назначаете место, на которое указывает ссылка.

Для компилятора следующие классы эквивалентны, обратите внимание, что версия указателя разыменовывает указатели для копирования содержимого:

class A_Ref{
public:
    A_Ref(U& u):u_(u){}
    A_Ref& operator=(const A_Ref& a){
        u_ = a.u_;
        return *this;
    }
    U& u_;
};

class A_Ptr{
public:
    A_Ptr(U* u):u_(u){}
    A_Ptr& operator=(const A_Ptr& a){
        *u_ = *a.u_;
        return *this;
    }
    U* u_;
};

Вам даже не нужно делать оператор присваивания частным, так как компилятор будет знать, что его не нужно генерировать, если есть константный член или ссылка. Они не могут быть переназначены.

Другие вопросы по тегам