Frage: NEW operator ueberladen



  • Moin,

    Ich habe mal eine Frage bezueglich des new und auch des delete operators.

    Es geht um folgendes: Ich moechte meine eigene Speicherverwaltung fuer die dynamisch erzeugten Daten erstellen, aber trotzdem noch die Moeglichkeit haben,
    auf die alte Speicherverwaltung zugreifen zu koennen.

    Wie ich die new und delete operatoren ueberlade ist relativ klar, aber nun zu der eigentlichen Frage: Ist es moeglich, wenn die new und delete Operatoren ueberladen sind, trotzdem noch auf das "alte" new und delete zuzugreifen und wenn ja wie?

    void* operator new(size_t requested_size) {
    	if (irgendeineBedingung) {
                   // eigene Speicherverwaltung
    	       return handler->allocateMemory(requested_size);
            } 
            // return altes new aufrufen! 
    }
    
    void operator delete(void* mem) {
    
     	handler->freeMemory(mem);
    }
    
    void* operator new[](size_t requested_size) {
    
    	return handler->allocateMemory(requested_size);
    }
    
    void operator delete[](void* mem) {
    
     	handler->freeMemory(mem);
    }
    

    Danke schonmal im Voraus!

    MfG & Ahoi
    sevenWaysToLove



  • Scott Meyers Kapitel über new/delete-Überladung durchlesen. *zurückerinner*, kanns eventuell ::new sein?

    MfG SideWinder



  • Wenn du die Operatoren global definiert hast, ersetzen sie die Default-Version. Wenn du sie als (statische) Member deiner Klasse hast (besser ist das ;)), gelten sie erstens nur für diese Klasse und ihre Nachkommen und können zweitens über ::operator new(...) etc auf die vordefinierten Versionen zugreifen.



  • CStoll schrieb:

    Wenn du die Operatoren global definiert hast, ersetzen sie die Default-Version.

    Kann man dadurch nicht auch das Verhalten der boost::shared_pointer, bzw generell Smart-Pointer als Standard definieren? Quasi: 'new' erstellt eine Instanz eines shared_pointer, der wiederum intern das gewünschte Objekt "verwaltet", mit allen Vorzügen der Smart Pointer.

    Wäre dies aus eurer Sicht klug oder weniger geeignet? Immerhin ließen sich dadurch viele Fehler bei der Behandlung von zur Laufzeit initierter Objekte lösen. Weiterhin könnte man danaben auch eine überladene Variante von ::delete anbieten, die den Speicher - wie auch bisher - weiterhin explizit freigibt.



  • uwe_guest schrieb:

    Kann man dadurch nicht auch das Verhalten der boost::shared_pointer, bzw generell Smart-Pointer als Standard definieren?

    Technisch so nicht möglich und auch nicht sinnvoll.



  • Moin,

    danke für die Antworten!

    @Sidewinder: Welches Buch von Scott Meyers meinst du genau?

    Also ich kann die Operatoren aus bestimmten Anforderungen leider nur global definieren, sonst würde ich auch eine Basisklasse verwenden ...

    MfG
    SevenWaysToLove 🙂



  • Da solltest du lieber dein Design überdenken - der globale operator new wird für ALLE Speicheranforderungen in deinem Programm verwendet, also solltest du schon genau wissen, was du da tust. (Randfrage: Was hast du eigentlich vor?)



  • @sevenWaysToLove: Effective C++

    MfG SideWinder



  • Schreib dir doch einen placement new.
    Da kannst du auch als Argument schön deine "irgendeineBedingung" übergeben und jenachdem dann dein eigens allocate oder globalen op-new aufrufen.
    Info: http://c-plusplus.net/forum/viewtopic-var-p-is-1194067.html#1194067

    Falls das nicht irgendwie dein Design kaputt macht ...



  • Wenns garnicht anders geht kannst du ::HeapAlloc und ::HeapFree mit dem "::GetProcessHeap()" verwenden.
    Würde ich aber nicht, sobald du DLLs verwendest und da Speicher rumreichst (und z.B. woanders löscht als du ihn angefordert hast) macht das "boom"...
    Und das kann schnell passieren´, reicht z.B. schon wenn man std::string's oder auch bloss irgendwelche Container rumreicht/returned.

    Alles in allem ist das in Windows ein ziemliches Problem den Allocator auszutauschen... was noch dazu schade ist, weil der Default Allocator volle Kanne lahm ist. 😞



  • Moin moin,

    ist zwar schon ein Weilchen her ...

    @CStoll: Eine eigene dynamische Speicherverwaltung hinterlegen, die auf dem globalen Speichersegment eines Prozesses abgebildet wird ...

    @all: Momentan haben sich die Anforderungen so geändert, dass das Problem
    ausgeschlossen werden kann, aber trotzdem danke an alle ! 👍

    MfG
    sevenWaysToLove



  • hab zwar keine ahnung wie das genau geht.
    aber in form von einer policy klasse geht das relativ hübsch.

    hier ein beispiel
    (ohne gewähr)

    template <typename T>
    class new_allocator
    {
     public:
      T* operator new() 
      { return ::new T() 
      }
    
      T* operator new[](size_t num)
      { return ::new T[num];
      }
    
      void operator delete(T* ptr)
      { ::delete ptr;
      }
      void operator delete[](T* ptr)
      { ::delete [] ptr;
      }
    };
    
    template<typename T>
    class CustomAllocator
    {
     static char* m_Heap[4096];
     static size_t m_Ptr;
    
     public:
      T* operator new()
      { 
        T* ptr = &m_Heap[m_Ptr];
        m_Ptr += sizeof(this);
        return ptr;
      } 
      T* operator new[](size_t num)
      {
        T* ptr = &m_Heap[m_Ptr];
        m_Ptr += sizeof(this) * num;
        return ptr;
      }
      void operator delete(T* ptr) { }; //do nothing
      void operator delete[](T* ptr) { }; //do nothing
    };
    
    template<typename T>
    class CustomAllocator::m_Ptr = 0;
    
    template<
     template <typename> allocator = new_allocator
    >
    class SomeClass : public allocator<SomeClass>
    {
     //code in here
    };
    
    SomeClass<> a;
    SomeClass<CustomAllocator> b;
    

Anmelden zum Antworten