einfach frage zu "new"



  • nebenbei: gibts eine Möglichkeit die Arraygröße von 100chars auf 200chars zu erhöhen ohne die ersten 100chars zu 'wipen' und dann den Speicher neu anzufordern?

    ➡ Mit realloc:

    char *buffer;
    buffer = new char [100];
    // ... 
    realloc(buffer, 200* sizeof(char) );
    

    Das einzige Problem könnte sein,dass eine Vergrösserung nicht möglich ist(, wenn z.B. nicht mehr genug freier Speicher verfügbar ist).




  • Administrator

    Ich würde dringend davon abraten, Speicherblöcke, welche mit new angelegt wurden, mit realloc zu verändern. new und delete gehören zusammen, das ist C++, während malloc, realloc und free zusammen gehören und C ist.

    Entweder, wie STDFREAK es gesagt hat, std::vector verwenden oder gerade für chars wäre std::string verfügbar.
    std::vector
    std::string

    Grüssli


  • Mod

    template <typename T>
    typename boost::enable_if< boost::is_pod< T >, T* >::type renew(const T* old_array, std::size_t old_size, std::size_t new_size)
    {
        T* new_array = new T[ new_size ];
        std::copy( old_array, old_array + std::min( old_size, new_size ), new_array );
        delete [] old_array;
        return new_array;
    }
    


  • warum muss T ein pod sein? copy macht doch keine flachen kopien.


  • Mod

    Falls T kein POD ist, werden beim new Defaultkonstruktoren aufgerufen und der Copyctor wirft evtl. eine Exception. Mit keinem dieser Probleme wollte ich mich hier herumschlagen, zumal es darauf keine idealen Antworten gibt. Es ist eben leider nicht (portabel) möglich, array-new im Programm aufzuteilen in Speicheranforderung und Initialisierung.
    Schön wäre so etwas

    // dieser Trick, um ggf. überladene new-operatoren zu finden (klappt allerdings nicht in exotischen Fällen)
    struct empty {};
    template <typename T>
    struct op_new_helper : boost::mpl::if_< boost::is_class< T >, T, empty >::type
    {
        typedef void* new_func(std::size_t);
        typedef void delete_func(void*);
        static new_func* const array_new_op;
        static delete_func* const array_delete_op;
    };
    
    template <typename T>
    typename op_new_helper< T >::new_func* const op_new_helper< T >::array_new_op = &operator new[]; // lookup des Initialisierers im Scope der Klasse
    template <typename T>
    typename op_new_helper< T >::delete_func* const op_new_helper< T >::array_delete_op = &operator delete[];
    
    template <typename T>
    T* renew_advanced(const T* old_array, std::size_t new_size)
    {
        std::size_t old_size = magic_func( old_array );
        T* new_array = reinterpret_cast< T* >( static_cast< char* >( op_new_helper< T >::array_new_op( new_size * sizeof( T ) + magic_value ) + magic_value ) );
        std::size_t initialized = 0;
        try
        {
            for ( ; initialized != std::min( old_size, new_size ); ++initialized )
                ::new( static_cast< void* >( new_array + initialized ) ) T( old_array[ initialized ] );
            for ( ; initialized != new_size; ++initialized )
                ::new( static_cast< void* >( new_array + initialized ) ) T();
        }
        catch ( ... )
        {
            for ( ; initialized--; )
                new_array[ initialized ].~T();
            op_new_helper< T >::array_delete_op( new_array );
            throw;
        }
        do_array_magic( new_array ); // zwecks Kompatibilität mit new T[ ... ]
        delete [] old_array;
        return new_array;
    }
    


  • STDFREAK schrieb:

    std::vector = dynamisches Array. Das macht das umkopieren für dich 🙂

    💡



  • Oder ohne STL:

    char *pcBuffer= new char[100];
    //Do something
    char *pcTempBuffer= new char[sizeof(pcBuffer)/sizeof(char) + 200];
    CopyMemory(pcTempBuffer,pcBuffer,sizeof(pcBuffer));
    delete[] pcBuffer;
    pcBuffer= pcTempBuffer;
    //Do something
    delete[] pcBuffer;
    

  • Administrator

    @Blaze,
    Ist das nicht ein wenig idiotisch, wenn man auf die STL, bzw. Standardbibliothek, verzichtet und dafür auf WinAPI Funktionen (CopyMemory) zurückgreift?

    Zudem, wieso sollte man std::vector nicht verwenden wollen? Was spricht dagegen? Und auch wenn du ohne std::vector auskommen möchtest, dann verwende zumindest die Standard-Algorithmen für das Kopieren des Chararrays, also std::copy !

    Zudem wird dein Code nicht funktionieren. sizeof(pcBuffer) wird dir auf einem 32-Bit System immer 4 und auf 64-Bit immer 8 zurückgeben. Und das ist so ein richtig typischer Grund, wieso solcher Code so fehleranfällig ist und man lieber die Standardbibliothek, also std::vector verwenden sollte!

    Grüssli



  • von der exception unsicherheit mal abgesehen 😉

    Ne, es kann aber durchaus gruende gegen std::vector geben - aber dann lautet die antwort "ein passenderer container". nackte arrays fasst man nicht an. nie. wenn man std::vector nicht verwenden will/kann/soll/... dann eben ein anderer container der ein array darstellt. zB boost::array oder aehnliches.



  • Dravere schrieb:

    Ich würde dringend davon abraten, Speicherblöcke, welche mit new angelegt wurden, mit realloc zu verändern.

    Nicht davon abraten. Strengstens verbieten! Das Mischen von new/delete und malloc/realloc/free führt zu undefiniertem Verhalten, Punkt. Wer sowas hier vorschlägt sollte sich dringendst nochmal mit einem guten C++-Buch auseinandersetzen bevor er hier weiter so hanebüchene Tips gibt.


Anmelden zum Antworten