'operator new': Funktion akzeptiert keine 2 Argumente
-
pumuckl schrieb:
was willst du mit der Zeile erreichen? Das hast vergessen dazuzuschreiben
Es ist doch offensichtlich, dass der Speicher, auf den 'm_ptr' zeigt, mit 'T's gefüllt werden soll. Und zwar Kopien der Elemente vom Parameter 'arr'.
-
Hast Du auch den Header
<new>
vorher eingebunden?
-
Sebastian Pizer schrieb:
Hast Du auch den Header
<new>
vorher eingebunden?Danke, das war das Problem. Ich wusste nicht, dass man für ein so grundlegendes Feature einen Header braucht.
-
Richtig richtig wird es, wenn das placement-Argument nach void* gecasted wird; andernfalls ist es denkbar, dass eine andere Überladung gewählt wird.
-
TyRoXx schrieb:
: m_ptr(reinterpret_cast<T*>(new char[count * sizeof(T)]))
Warum
reinterpret_cast
und der Umweg überchar[]
? Machs doch so:: m_ptr(static_cast<T*>(operator new(count * sizeof(T))))
Wobei ich eher empfehle, für sowas eine Funktion zu schreiben:
T* allocate(size_t count) { return static_cast<T*>(operator new(count * sizeof(T))); }
: m_ptr(allocate<T>(count))
-
Du weist doch genau, wieso^^
Beim Vektor/vector find ich das auch sinnvoll - es muss nicht zwangsläufig nen standard-konstruktor geben und vor allem will ich nicht, dass er mir unkontrolliert viele objekte erstellt, von denen ich gar nichts weiß...
beim string wiederrum ists egal.bb
-
Nexus schrieb:
TyRoXx schrieb:
: m_ptr(reinterpret_cast<T*>(new char[count * sizeof(T)]))
Warum
reinterpret_cast
und der Umweg überchar[]
? Machs doch so:: m_ptr(static_cast<T*>(operator new(count * sizeof(T))))
Wobei ich eher empfehle, für sowas eine Funktion zu schreiben:
T* allocate(size_t count) { return static_cast<T*>(operator new(count * sizeof(T))); }
: m_ptr(allocate<T>(count))
reinterpret_cast
, weilstatic_cast
nicht ausreicht, um Zeiger zu konvertieren (error C2440).
Zum Freigeben des Speichers nimmt man dannoperator delete[](void*)
oder wie?
-
Jopp...
aber stattnew char[]
nimmt man eigtloperator new[]
:template<typename T> void foo(size_type size) { void *memory_block = operator new[size * sizeof(T)]; size_type i = size_type(); try { for(; i != size; ++i) { new(memory_block + i*sizeof(T)) T(); } } catch(...) { for(; i != 0; ++i) { reinterpret_cast<T*>(memory_block + (i-1)*sizeof(T))->~T(); } throw; } //mach was... for(size_type i = size_type(); i != size; ++i) { reinterpret_cast<T*>(memory_block + i*sizeof(T))->~T(); } operator delete[] memory_block; }
ist ziemlich hässlich, aber sollte die vorgehensweise verdeutlichen^^
das ganze macht man aber normalerweise über nen allocator...bb
-
TyRoXx schrieb:
reinterpret_cast
, weilstatic_cast
nicht ausreicht, um Zeiger zu konvertieren (error C2440).Er reicht schon aus, allerdings nur von
void*
zuT*
und umgekehrt oder in Klassenhierarchien.TyRoXx schrieb:
Zum Freigeben des Speichers nimmt man dann
operator delete(void*)
oder wie?Ja, genau. Aber vorher nicht vergessen, den Destruktor über
ptr->~T()
aufzurufen.
-
unskilled schrieb:
aber statt
new char[]
nimmt man eigtloperator new[]
:template<typename T> void foo(size_type size) { void *memory_block = operator new[size * sizeof(T)];
Das sieht aber komisch aus. Ich programmiere nicht so oft std::vector nach, deswegen bin ich bei diesem operator new-Kram nicht so fit. Aber ich würde raten, dass das wenn überhaupt
::operator new[](size * sizeof(T));
heißen müsste. void* finde ich in diesem Fall recht unpraktisch.size_type i = size_type();
Hmm.. hätte einfach
=0;
geschrieben. Man muss das ja nicht alles so kompliziert machen. :ptry { for(; i != size; ++i) { new(memory_block + i*sizeof(T)) T();
Zeigerarithmetik auf void* ?
} } catch(...) { for(; i != 0; ++i) { reinterpret_cast<T*>(memory_block + (i-1)*sizeof(T))->~T();
Zeigerarithmetik auf void* ?
Außerdem: Es müsste --i in der Schleife sein, nicht?operator delete[] memory_block;
sieht auch komisch aus. Fehlen da nicht die Klammern um
memory_block
?Gruß,
SP
-
Japp - da waren ziemlich viele Fehler drin - ist eben schon ne ganze Zeit her und ich dachte, ich bekomms noch so ausm Stehgreif hin :S
so sollte es stimmen:
(und sieht auch schon um einiges besser aus ;o))#include <new> typedef std::size_t size_type; template<typename T> void foo(size_type size) { T *memory_block = static_cast<T*>( ::operator new(size * sizeof(T)) ); size_type i = size_type(); try { for(; i != size; ++i) { new(memory_block + i) T(); } } catch(...) { for(; i != 0; --i) { memory_block[i].~T(); } throw; } //mach was... for(size_type i = size_type(); i != size; ++i) { memory_block[i].~T(); } ::operator delete ( static_cast<void*>(memory_block) ); } int main() { foo<int>(45678); }
hätte einfach =0; geschrieben. Man muss das ja nicht alles so kompliziert machen.
kA, ich bin da immer bissl warning-paranoid^^ vll gibts ja auch irgendwo mal nen so eigenartigen size_type, bei dem irgend nen compiler unnötigerweise ne warning von sich gibt, wenn man ihm nen int zuweist...
und unübersichtlicher find ich es auch nicht...bb
-
unskilled schrieb:
catch(...) { for(; i != 0; --i) { memory_block[i].~T(); } throw; }
<räusper>Ähäm</räusper>
while (i>0) memory_block[--i].~T();
-
geschmackssache?
-
Wenn, dann
while(i > 0) memory_block[i--].~T();
-
Oder man schreibt sich vernünftige Funktionen für sowas.
destroy_range(memory_block, memory_block+size);
-
doch nix mit geschmackssache xD
hast recht, da ist nen fehler drin...for(; i != 0; --i) { memory_block[i-1].~T(); }
oder deine(SP) Lösung...
das i-te Element dort wurde ja noch nicht erstellt -> kann nicht freigegeben werden... bäm!
bb
-
wx++ schrieb:
Wenn, dann
while(i > 0) memory_block[i--].~T();
Nein, das eben nicht! Mir ging's nicht um for<->while sondern genau um die Indizes.
-
Ja, du hast Recht.
Ich hab's einfach blind von seinem Code übernommen.