einfach frage zu "new"
-
char *buffer; buffer = new char [100]; // *...some other code...* buffer = new char [200];Wie groß wäre das Array am ende des codes? 200 oder 300 Bytes?
Oder anders gefragt wird Speicher zusätzlich reserviert oder die ersten 100 Bytes überschrieben?
-
Hallo,
du weist dem Pointer buffer ein neu erzeugtes Array der Länge 200 zu, also enthält das Array, auf das der Pointer zeigt, logischerweise 200 chars. Das alte Array mit 100 Elementen verwaist allerdings -> Dein Programm leaked!
-
Ah verstehe, dann sollte es so richtig stein denke ich mal (ohne memoryleak):
char *buffer; buffer = new char [100]; // *other code* delete []buffer; buffer = new char [200]; // *other code* delete []buffer;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?
-
newbie_cpp schrieb:
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?
Nein. Du müsstest zuerst neuen Speicher in der gewünschten Größe anfordern, den alten nicht mehr benötigten Bereich umkopieren, und dann den alten Speicher freigeben, wenn Du den Inhalt noch zu Beginn des neuen, größeren Speichers behalten willst. Du brauchst dann natürlich einen zweiten Zeiger.
-
Danke für die schnelle Hilfe

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

-
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).
-
Ahh! Nein. Vergiss das sofort. http://www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.5
-
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::vectorverwenden oder gerade für chars wärestd::stringverfügbar.
std::vector
std::stringGrüssli
-
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.
-
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;
-
@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::vectornicht verwenden wollen? Was spricht dagegen? Und auch wenn du ohnestd::vectorauskommen möchtest, dann verwende zumindest die Standard-Algorithmen für das Kopieren des Chararrays, alsostd::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, alsostd::vectorverwenden 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.