= Operator spinnt?



  • Hallo allerseits 🙂

    Ich habe eine variant-Klasse geschrieben, die ein beliebiges Objekt beinhalten kann. Ich kann allerdings u.a. das verhalten des = Operators nicht nachvollziehen. Wenn ich einem Variant-Objekt ein anderes Variant-Objekt zuweise, dann müsste doch das erste Objekt das ganze andere Objekt beinhalten und nicht nur dessen inhalt (in diesem Beispiel der String). Oder ist es ein Sonderfall weil es zwei Objekte vom selben Typ sind? Hat jemand eine Idee was da genau abgeht?

    #ifndef VARIANT_H
    #define VARIANT_H
    
    #include <cstdlib>
    
    class variant
    {
        public:
            // constructor
            variant()
            {
                m_size = 0;
                m_data = NULL;
                }
            // initializer constructor
            template <typename T>
            variant(const T &obj)
            {
                store(&obj);
                }
            // copy constructor
            variant(const variant &v)
            {
                m_size = v.m_size;
                free(m_data);
                m_data = malloc(m_size);
                memcpy(m_data, v.m_data, m_size);
                }
            // destructor
            virtual ~variant()
            {
                free(m_data);
                }
            // = operator
            template <typename T>
            variant& operator = (const T &obj)
            {
                store(&obj);
                }
            // get object data
            template <typename T>
            T get()
            {
                return *((T*)m_data);
                }
            // get object size
            size_t size()
            {
                return m_size;
                }
    
        private:
            // store object in variant
            template<typename T>
            void store(const T *obj)
            {
                free(m_data);
                m_size = sizeof(T);
                m_data = malloc(m_size);
                memcpy(m_data, obj, m_size);
                }
            // object size    
            size_t  m_size;
            // object data
            void   *m_data;
        };
    
    #endif
    

    Das geht:

    #include <cstdlib>
    #include <iostream>
    #include <string>
    #include "variant.h"
    
    using namespace std;
    
    int main(int argc, char *argv[])
    {
    
        variant x = string("Hallo");
        variant y;
    
        y = x;
    
        cout << y.get<string>() << endl;
    
        system("PAUSE");
        return EXIT_SUCCESS;
        }
    

    Das geht nicht (crash), obwohl es meiner Meinung nach logischer wäre:

    #include <cstdlib>
    #include <iostream>
    #include <string>
    #include "variant.h"
    
    using namespace std;
    
    int main(int argc, char *argv[])
    {
    
        variant x = string("Hallo");
        variant y;
    
        y = x;
    
        cout << (y.get<variant>()).get<string>() << endl;
    
        system("PAUSE");
        return EXIT_SUCCESS;
        }
    


  • malloc -> nur PODs

    hab gar nicht weitergelesen


  • Mod

    Ein Templateoperator ist niemals ein Copyzuweisungsoperator und ein Templatekonstruktor niemals ein Copykonstruktor. Diese werden implizit durch den Compiler deklariert (da du es nicht tust) und dann entsprechend aufgerufen. Man könnte auch sagen, der erste Satz folgt aus dem Zweiten, aber oft lässt man den letzten Teil auch weg und dann sieht das plötzlich wie eine besondere Regel aus, obwohl es eigentlich keine ist.



  • Wenn ich die beiden folgenden methoden definiere:

    template <typename T>
    variant& operator = (const T &obj)
    
    variant& operator = (const variant &v)
    

    Kann ich dann davon ausgehen, dass 1. immer dann verwendet wird, wenn 2. nicht geht?



  • Du solltest weiterhin die Selbstzuweisung mit:

    if(this != &obj)
    

    ausschließen.



  • Eigentlich braucht er das nicht, sofern die Logik korrekt ist. Was allerdings nicht der Fall ist. Das würde ich eher ändern.



  • Zumindests beim Zuweisungsoperator fehlt ein "return *this;" ...
    Daher kann die Zuweisung "y = x;" nur Müll ausgeben.

    (Falls das überhaupt so kompiliert!)



  • Langsam geht mir auf, dass meine Klasse ziemlicher Müll ist. 🤡
    Ich kann ja mit sizeof gar nicht die korrekte Objektgrösse ermitteln. Ich müsste die Objekte jeweils mit new duplizieren. Da aber die daten in einem void-Pointer gespeichert werden, kann ich den Speicher nicht mit delete freigeben. 🙂



  • Deine Klasse funktioniert - zumindest solange du sie nur mit PODs füllst (POD=Plain Old Data - das sind vereinfacht ausgedrückt Datentypen, die auch in C vorkommen könnten). Wenn du mit vollwertigen C++ Klassen arbeiten willst, hast du schon ein Problem - du kannst mit deinem Ansatz nicht feststellen, welchen Datentyp du in deinem variant gespeichert hast, aber du brauchst diesen Typ, um deine Daten korrekt zu kopieren.


Anmelden zum Antworten