Verständnis - 'Class XY' has pointer data members



  • Hallo,

    es handelt sich nur um ein Beispiel. Allerdings würde ich es gerne verstehen.

    warning: 'class CreateHeader' has pointer data members|
    warning: but does not override 'CreateHeader(const CreateHeader&)'|
    warning: or 'operator=(const CreateHeader&)'|

    Bsp.:

    class CreateHeader
    {
        public:
            CreateHeader();
            void Methode();
            virtual ~CreateHeader();
        protected:
        private:
            char * pBuf;
    };
    

    Ich habe weder einen Copy-Konstruktor bzw. Operator-Überladung.

    Ich frage mich nur, wieso er das möchte? Was würde sonst passieren?

    Der Compiler erstellt Copy-Konstruktor/Operator-Überladung automatisch, falls keiner vorhanden ist.

    Aber was ich gerne verstehen würde ist, warum er dort einen benötigt?
    Also was läuft intern ab?

    Danke
    😕 😕



  • Es ist eine Warnung, dass der automatisch generierte Kopierkonstruktor/Zuweisungsoperator höchstwahrscheinlich nicht das macht, was du erwartest.

    Die kritische Frage hier ist: erzeugst du den Speicherplatz für pBuf mit new? Gibst du ihn auch wieder mit delete frei?



  • Es ist eigentlich ein alter Sourcecode, den ich mal zum testen geschrieben habe.
    Der Speicher wird nicht manuell(new) allokiert wird für pBuf.

    Das Objekt wird glaube ich erstellt und die Methode ( Methode() ) innerhalb einer Schleife 2,3 mal durchläuft.

    Ich frage mich halt nur, warum eben in solch einem Fall dieser benötigt wird?
    Also was steckt dahinter?

    Also ich weiß, das z.B. innerhalb eines Kopie-Konstruktors neuer Speicher für den Zeiger allokiert werden muss. Aber frage mich halt warum ^^.. 🙄

    Ich hoffe, dass jemand meine Frage versteht 🙄



  • Wenn Du in einem Konstruktor new und in einem Destruktor delete auf einem Memberzeiger aufrufst, erzeugen der compilergenerierte Kopierkonstruktor und Zuweisungsoperator ein Speicherleck, da nur der Zeiger kopiert wird. Das führt dazu, dass zwei Destruktoren den gleichen Zeiger löschen wollen. Davor warnt Dich der Compiler.



  • LordJaxom schrieb:

    Wenn Du in einem Konstruktor new und in einem Destruktor delete auf einem Memberzeiger aufrufst, erzeugen der compilergenerierte Kopierkonstruktor und Zuweisungsoperator ein Speicherleck, da nur der Zeiger kopiert wird. Das führt dazu, dass zwei Destruktoren den gleichen Zeiger löschen wollen. Davor warnt Dich der Compiler.

    Ich allokiere aber nichts manuell...



  • -Weffc++ warnungen sind manchmal nicht sinvoll.
    Ich denke GCC kann nicht erkennen, dass du wirklich pointer kopieren möchtest.



  • zuckerlie schrieb:

    Ich allokiere aber nichts manuell...

    Der Compiler ist aber nicht so schlau, das zu erkennen.

    Das Muster ist einfach "Klasse enthält Pointer, hat aber kein Destruktor, Copyconstructur und Zuweisungsoperator -> Warnung".



  • Ich sehe gerade noch innerhalb der cpp.

    pBuf = strtok(data,"#");
    ..
    pBuf = strtok(NULL,"#");
    ..
    ..
    

    pBuf ist der Verweis auf die vom strtok zurückgegebenen token
    Also brauch er keinen Copy-Constructor und ich kann ihn private setzen, damit nicht unnötig ein Copy-Constructor erstellt wird?



  • zuckerlie schrieb:

    Bsp.:

    class CreateHeader
    {
        public:
            CreateHeader();
            void Methode();
            virtual ~CreateHeader();
        protected:
        private:
            char * pBuf;
    };
    

    warning: 'class CreateHeader' has pointer data members
    warning: but does not override 'CreateHeader(const CreateHeader&)'
    warning: or 'operator=(const CreateHeader&)'

    Welcher Compiler sagt das bei welchen Einstellungen? Die Begrüdung finde ich komisch. Ich hätte da auch gewarnt. Aber nicht wegen dem Pointer-Datenelement, sondern weil Du einen Destruktor selbst deklariert hast; denn nach C++11 Regeln ist in dem Fall die automatische Erzeugung der Kopieroperationen deprecated.

    zuckerlie schrieb:

    Aber was ich gerne verstehen würde ist, warum er dort einen benötigt?

    "Tut er" nicht. Es ist lediglich eine Warnung nach dem Motto "Das sieht komisch aus. Bist Du Dir sicher, dass das so soll?". Wenn Du den Compiler im C++11-Modus betreibst, kannst Du die Warnungen wegbekommen, in dem Du explizit sagst, was da bzgl Kopieroperationen passieren soll, also entweder so:

    class CreateHeader
    {
        public:
            CreateHeader();
            ~CreateHeader();
            void Methode();
    
            CreateHeader(CreateHeader const&) = default;
            CreateHeader& operator=(CreateHeader const&) = default;
        protected:
        private:
            char * pBuf;
    };
    

    oder so

    class CreateHeader
    {
        public:
            CreateHeader();
            ~CreateHeader();
            void Methode();
    
            CreateHeader(CreateHeader const&) = delete;
            CreateHeader& operator=(CreateHeader const&) = delete;
        protected:
        private:
            char * pBuf;
    };
    

    Ich würde die Warnung aber ernst nehmen. Die Klasse sieht mir auch suspekt aus. Warum deklarierst Du den Destruktor selbst und warum auch noch virtuell?!



  • LordJaxom schrieb:

    Das Muster ist einfach "Klasse enthält Pointer, hat aber kein Destruktor, Copyconstructur und Zuweisungsoperator -> Warnung".

    Die Klasse enthält eine Deklaration des Destruktors (und sonst nichts an "special member functions"). Das ist meiner Meinung nach ein würdiger Warnungsgrund -- 3er-Regel-technisch. Am Pointer Element würde ich das gar nicht festmachen.



  • wenn pBuf nur in Methode benötigt wird, solltest du ihn vielleicht auch nur dort anlegen und nicht in die Klasse packen?

    greetz KN4CK3R



  • krümelkacker schrieb:

    Die Klasse enthält eine Deklaration des Destruktors (und sonst nichts an "special member functions"). Das ist meiner Meinung nach ein würdiger Warnungsgrund -- 3er-Regel-technisch. Am Pointer Element würde ich das gar nicht festmachen.

    Du vielleicht nicht. Der Compiler (zumindest nach dem exakten Wortlaut der Warnung - und Compilerhersteller sollten bei sowas eigentlich genau sein) schon. 🙂



  • Vielen Dank erstmal!

    Ich hatte ihn (glaube ich damals virtuell gemacht, weil ich irgendwas vererben wollte - weiß es nicht mehr).
    Die Klasse war damals ja nur zu Testzwecken. Ich wollt mir das einfach mal anschauen was ich da so produziert habe.

    Es handelt sich um die MinGW 4.6.2



  • GCC/G++ gibt solche Warnungen aber nur aus, wenn die Option -Weffc++ spezifiziert ist. Der passende Teil der Manpage sagt dazu:

    GCC Manpage schrieb:

    -Weffc++ (C++ and Objective-C++ only)
    Warn about violations of the following style guidelines from Scott Meyers' Effective C++ book:

    · Item 11: Define a copy constructor and an assignment operator for classes with dynamically allocated memory.

    · Item 12: Prefer initialization to assignment in constructors.

    · Item 14: Make destructors virtual in base classes.

    · Item 15: Have "operator=" return a reference to *this.

    · Item 23: Don't try to return a reference when you must return an object.

    Also warn about violations of the following style guidelines from Scott Meyers' More Effective C++ book:

    · Item 6: Distinguish between prefix and postfix forms of increment and decrement operators.

    · Item 7: Never overload "&&", "||", or ",".

    When selecting this option, be aware that the standard library headers do not obey all of these guidelines; use grep -v to filter out those warnings.

    Weder -Wall, noch -Wextra enthalten diese Option.


Log in to reply