Оператор присваивания со ссылочными элементами - PullRequest
29 голосов
/ 26 октября 2011

Является ли это допустимым способом создания оператора присваивания с элементами, которые являются ссылками?

#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;
    }
}

Кажется, что он компилируется и работает нормально, но с тенденцией c ++ отображать неопределенное поведение, когда это меньше всего ожидается, и вселюди, которые говорят, что это невозможно, я думаю, что есть кое-что, что я пропустил.Я что-то пропустил?

Ответы [ 4 ]

35 голосов
/ 26 октября 2011

Это синтаксически правильно. Если размещение новых бросков, однако, вы в конечном итоге с объектом, который вы не можете разрушить. Не говоря уже о катастрофе если кто-то происходит из вашего класса. Просто не делай этого.

Решение простое: если класс должен поддерживать присваивание, не используйте любые ссылочные элементы. У меня есть много классов, которые берут ссылку аргументы, но храните их как указатели, просто чтобы класс мог поддерживать назначение. Что-то вроде:

struct A
{
    int* myRef;
    A( int& ref ) : myRef( &ref ) {}
    // ...
};
6 голосов
/ 15 марта 2016

Другое решение заключается в использовании класса 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_;

};
4 голосов
/ 26 октября 2011

То, что вы делаете, технически правильно, насколько я знаю, но это порождает проблемы. Например, рассмотрим, что происходит с производным классом из A, поскольку его оператор присваивания генерирует новый объект (нарезку) Разве вы не можете просто превратить ссылку в указатель в вашем классе?

Кроме того, конструкторы копирования и операторы присваивания обычно принимают аргумент const&.

1 голос
/ 26 октября 2011

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

Вы должны реализовать это, используя Копировать и поменять местами . Он имеет по крайней мере 3 преимущества по сравнению с вашей реализацией.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...