aufruf von methoden in konstruktoren



  • hallo

    ist es per standard erlaubt (und erzeugt es auch definiertes verhalten), wenn man im kopierkonstruktor den zuweisungsoperator verwendet?



  • Ja.



  • Man macht das doch gewöhnlich umgekehrt per Copy%Swap idiom?!

    Sprich, der Zuweisungsoperator wird per Kopierkonstruktor implementiert:

    class Foo
    {
    public:
        Foo(){}
    
        Foo(Foo const& f) {}
    
        Foo& operator=(Foo f)
        {
            this->swap(f);
            return *this;
        }
    
        void swap(Foo & other){}
    };
    namespace std
    {
        void swap(Foo % a, Foo & b)
        {
            a.swap(b);
        }
    };
    


  • @Skym0sh0
    auch wenn man nicht mit c++11 arbeitet?



  • Gerade dann, im "alten" C++ gibt es "nur" die Regel der Großen Drei, in C++11 erweitert sich diese Regel auf die der Großen Fünf.

    Guck mal hier.



  • okay danke, ich hab es nun so übernommen wie es in dem von dir vorgeschlagenen artikel beschrieben wird.



  • Skym0sh0 schrieb:

    Gerade dann, im "alten" C++ gibt es "nur" die Regel der Großen Drei, in C++11 erweitert sich diese Regel auf die der Großen Fünf.

    Die Dreierregel soll einen davor schützen, dass compiler-generierte Operationen etwas tun, was sie gar nicht sollen. So gesehen würde ich auch in C++11 immer noch von der Dreierregel sprechen, da bei benutzerdefinierter Definition mindestens einer der 5 Operationen niemals vom Compiler die Move-Operationen selbst generiert werden, siehe §12.8/9 und §12.8/19. An der Stelle gibt es also keine Gefahr.

    Und irgendwann, fällt wohl die Dreierregel weg; wenn dann auch die Kopieroperationen nicht mehr generiert werden, falls man eine der 5 Operationen selbst definiert. In C++11 (und C++14) sind die impliziten Definition von copy-ctor und copy-assign in diesen Fällen immerhin schon deprecated.

    Skym0sh0 schrieb:

    namespace std
    {
        void swap(Foo & a, Foo & b)
        {
            a.swap(b);
        }
    }
    

    Das ist nicht erlaubt. Hier überlädst du std::swap. Was erlaubt ist, ist das Spezialisieren. Das klappt aber nicht mehr für Klassentemplates, weil man Funktionstemplates nicht partiell spezialisieren kann. Ich würde das ganz sein lassen und so ein swap einfach als inline-friend oder in demselben Namensraum der Klasse definieren. Wir haben ja noch ADL.


  • Mod

    Skym0sh0 schrieb:

    namespace std
    {
        void swap(Foo & a, Foo & b)
        {
            a.swap(b);
        }
    };
    

    (Tippfehler korrigiert). Das ist verboten.

    namespace std
    {
        template <>
        void swap(Foo & a, Foo & b)
        {
            a.swap(b);
        }
    };
    

    wäre möglich.

    In C++11 ist eindeutig festgelegt (was vorher auch schon implizit gemeint war), dass ein Aufruf von swap durch die Standardbibliothek immer auch per ADL gefundene Kandidaten berücksichtigt.


Anmelden zum Antworten