Оператор присваивания с ссылочными элементами
Является ли это допустимым способом создания оператора присваивания с элементами, которые являются ссылками?
#include <new>
struct A
{
int &ref;
A(int &Ref) : ref(Ref) { }
A(const A &second) : ref(second.ref) { }
A &operator =(const A &second)
{
if(this == &second)
return *this;
this->~A();
new(this) A(second);
return *this;
}
}
Кажется, он компилируется и работает нормально, но с склонностью С++ к поверхностному поведению undefined, когда наименее ожидаемый, и всем людям, которые говорят, что это невозможно, я думаю, что есть некоторые gotcha, которые я пропустил. Я что-то пропустил?
Ответы
Ответ 1
Синтаксически корректно. Однако, если размещение новых бросков, вы
в конечном итоге с объектом, который вы не можете уничтожить. Не говоря уже о катастрофе
если кто-то вытекает из вашего класса. Только не делай этого.
Решение прост: если класс должен поддерживать назначение, не
используйте любые ссылочные элементы. У меня много классов, которые берут ссылку
аргументы, но сохраните их в качестве указателей, так что класс может поддерживать
назначение. Что-то вроде:
struct A
{
int* myRef;
A( int& ref ) : myRef( &ref ) {}
// ...
};
Ответ 2
Что вы делаете, насколько мне известно, технически корректно, но это порождает проблемы. Например, рассмотрите, что происходит с производным классом из A
, так как его оператор присваивания генерирует новый объект (разрезание). Не можете ли вы просто превратить ссылку в указатель внутри своего класса?
Кроме того, конструкторы копирования и операторы присваивания обычно принимают свой аргумент const&
.
Ответ 3
Что вы делаете правильно, но это не очень безопасный способ написания оператора присваивания копий. Кроме того, вам следует рассмотреть возможность использования элемента-указателя, а не элемента ссылки.
Вы должны реализовать его, используя Идиома копирования и свопинга. Это по крайней мере 3 преимущества по сравнению с вашей реализацией.
Ответ 4
Другим решением является использование класса reference_wrapper (в функциональном заголовке):
struct A
{
A(int& a) : a_(a) {}
A(const A& a) : a_(a.a_) {}
A& operator=(const A& a)
{
a_ = a.a_;
return *this;
}
void inc() const
{
++a_;
}
std::reference_wrapper<int>a_;
};