Operator przydziałów z członkami referencyjnymi

Czy jest to prawidłowy sposób tworzenia operatora przypisania z członkami, które są referencjami?

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

Wydaje się kompilować i działać dobrze, ale z C++ tendencja do powierzchni niezdefiniowanego zachowania, gdy najmniej oczekiwane, i wszystkich ludzi, którzy mówią, że to niemożliwe, myślę, że jest pewne gotcha brakowało. Coś mnie ominęło?

Author: Dani, 2011-10-26

4 answers

Jest poprawna składniowo. Jeśli umieszczenie nowych rzuca, jednak, można kończy się z obiektem, którego nie można zniszczyć. Nie wspominając o katastrofie jeśli ktoś pochodzi z twojej klasy. Po prostu tego nie rób.

Rozwiązanie jest proste: jeśli klasa musi obsługiwać przypisanie, nie użyj dowolnych członków odniesienia. Mam wiele zajęć, które odnoszą się argumenty, ale przechowuj je jako wskaźniki, tak aby Klasa mogła obsługiwać zadanie. Coś w stylu:

struct A
{
    int* myRef;
    A( int& ref ) : myRef( &ref ) {}
    // ...
};
 44
Author: James Kanze,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-26 17:14:20

Innym rozwiązaniem jest użycie klasy reference_wrapper (w nagłówku funkcyjnym):

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_;

};
 7
Author: alangab,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-15 11:29:58

To, co robisz, jest technicznie poprawne, o ile wiem, ale generuje kłopoty. Na przykład, rozważmy, co dzieje się z klasą pochodną z A, ponieważ jej operator przypisania generuje nowy obiekt (slicing). Nie możesz po prostu zmienić referencji W wskaźnik w swojej klasie?

Poza tym konstruktory kopiujące i operatory przypisania zwykle przyjmują argument przez const&.

 4
Author: K-ballo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-26 17:00:08

To co robisz jest poprawne, ale nie jest to bardzo bezpieczny sposób pisania operatora przypisania kopii. Należy również rozważyć użycie elementu wskaźnikowego, a nie elementu referencyjnego.

Powinieneś zaimplementować go używając idiom Copy and Swap. Ma co najmniej 3 zalety w stosunku do Twojej implementacji.

 1
Author: Alok Save,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:06:48