Map mit Template Typen
-
Ja ich wollte mich jetzt nicht von dem unique_ptr abhängig machen.
Was bitte soll das heißen?
Das klingt jetzt vielleicht doof, aber ich mag es nicht mit dem zu arbeiten.
Das klingt tatsächlich doof, den der
unique_ptrist eigentlich Pflicht in modernem C++.Ich kümmer mich lieber selbst um den Speicher.
Hier ist das vielleicht noch irgendwie in Ordnung, aber glaub mir, diese Devise solltest du ganz schnell vergessen.
-
DuffCola schrieb:
Das klingt jetzt vielleicht doof, aber ich mag es nicht mit dem zu arbeiten.
Nein, das klingt ganz und gar nicht doof, das ist doof! Benutze RAII wann immer es geht!
-
Wahrscheinlich meint er, weil er rohe Pointer benutzt holt er Geschwindigkeit raus.
Aber er weis nicht, was er macht daher...
-
Wahrscheinlich meint er, weil er rohe Pointer benutzt holt er Geschwindigkeit raus.
Prinzipiell verursacht ein
unique_ptrkeinen Overhead. Er hat dieselbe Größe wie der Zeiger,hält keine anderen Member*, und alle Operationen die er implizit erledigt, muss man auch selbst erledigen.Ich habe es nicht getestet, bin mir aber sehr sicher dass der Overhead absolut minimal sein dürfte.
*: Nein, es muss ja technisch gesehen noch den Deleter halten. S. Seite 2.
-
std::unique_ptr ist genauso ein Teil der Standardbibliothek wie std::map, sogar deutlich leichter zu implementieren. Also wenn du unique_ptr nicht willst weil dein Spiel auch auf einer Armbanduhr laufen soll, dann bitte auch std::map selbst implementieren.

-
@DuffCola (aber auch Sone und cooky451): unique_ptr hat nicht minimalen Overhead, sondern rein gar keinen.
Es ist tatsächlich nicht klug, in C++ Speicher manuell verwalten zu wollen. Du machst dir das Leben nur schwerer, ohne irgendeinen Vorteil davon zu haben. Die Leute in diesem Buch haben sich schon was überlegt

-
unique_winner schrieb:
unique_ptr hat nicht minimalen Overhead, sondern rein gar keinen.
Das bezweifle ich. (Ich weiß es wie gesagt nicht, schätze aber, dass in bestimmten Situationen ein Funktionsaufruf o.ä. Overhead verursachen könnte. )
und cooky451
Was hat cooky damit zu tun? Er hat keine Aussage über den Overhead gemacht.
-
Die Memberfunktionen von unique_ptr werden komplett geinlined, da ist absolut 0 Overhead.
-
Nein, tatsächlich muss unique_ptr sogar einen zweiten Member halten (bzw. irgendwie auf ihn Verweisen): Den Deleter.
Die Memberfunktionen von unique_ptr werden komplett geinlined, da ist absolut 0 Overhead.
Das wird schon stimmen. Auch die vom Deleter? Sicher, auch die. Dann vielleicht tatsächlich kein Overhead.
-
Sone schrieb:
Nein, tatsächlich muss unique_ptr sogar einen zweiten Member halten (bzw. irgendwie auf ihn Verweisen): Den Deleter.
Was im Falle des hier nur interessanten default_delete<T> keinen Overhead darstellt (da leere Klasse), eine vernünftige Implementierung unterstellt.
-
unique_winner schrieb:
@DuffCola (aber auch Sone und cooky451): unique_ptr hat nicht minimalen Overhead, sondern rein gar keinen.
Naja, unique_ptr kann schon Overhead haben.
Beispielcode:
namespace { template <typename T> struct unique_ptr { T* data; unique_ptr(T* data) : data(data) {} unique_ptr(unique_ptr&& o) : data(o.data) { o.data = 0; } ~unique_ptr() { delete data; } }; unique_ptr<int> make_unique(int v) { return unique_ptr<int>(new int(v)); } int* make_ptr(int v) { return new int(v); } } void f() { auto i = make_unique(0); } void g() { auto i = make_ptr(0); delete i; }gcc mit -O2 -fno-elide-constructors liefert:
f:
.cfi_startproc pushq %rbx .cfi_def_cfa_offset 16 .cfi_offset 3, -16 movl $4, %edi call _Znwm xorl %edi, %edi movl $0, (%rax) movq %rax, %rbx call _ZdlPv xorl %edi, %edi call _ZdlPv movq %rbx, %rdi popq %rbx .cfi_def_cfa_offset 8 jmp _ZdlPv .cfi_endprocg:
.cfi_startproc subq $8, %rsp .cfi_def_cfa_offset 16 movl $4, %edi call _Znwm movl $0, (%rax) movq %rax, %rdi addq $8, %rsp .cfi_def_cfa_offset 8 jmp _ZdlPv .cfi_endprocBei einem gcc mit -fno-elide-constructors sieht allerdings beides gleich aus.
Sone schrieb:
Nein, tatsächlich muss unique_ptr sogar einen zweiten Member halten (bzw. irgendwie auf ihn Verweisen): Den Deleter.
Lern erst einmal C++ bevor du irgendwelche Behauptungen aufstellst. Stichwort EBO.
-
Lern erst einmal C++ bevor du irgendwelche Behauptungen aufstellst. Stichwort EBO.
Ich kenne C++. Laut Standard muss
unique_ptreinen Deleter halten. Wenn dieser 0 Bytes groß ist, wie beidefault_deleter, wird er als Member auch wegoptimiert.
-
shared_disadvantage schrieb:
Stichwort EBO.
Bzw. optimal wäre
tuple<T*, Deleter>.
-
Sone schrieb:
Lern erst einmal C++ bevor du irgendwelche Behauptungen aufstellst. Stichwort EBO.
Ich kenne C++. Laut Standard muss
unique_ptreinen Deleter halten. Wenn dieser 0 Bytes groß ist, wie beidefault_deleter, wird er als Member auch wegoptimiert.Basiswissen C++: Member dürfen nicht wegoptimiert werden.
-
shared_disadvantage schrieb:
Stichwort EBO.
Bzw. optimal wäre
tuple<T*, Deleter>.Ja, so macht es der GCC.
-
shared_disadvantage schrieb:
Sone schrieb:
Lern erst einmal C++ bevor du irgendwelche Behauptungen aufstellst. Stichwort EBO.
Ich kenne C++. Laut Standard muss
unique_ptreinen Deleter halten. Wenn dieser 0 Bytes groß ist, wie beidefault_deleter, wird er als Member auch wegoptimiert.Basiswissen C++: Member dürfen nicht wegoptimiert werden.
Eine Klasse muss mindestens einen Byte groß sein, da jedes Objekt eine Adresse haben muss.
Und das wird bei Membern nicht wegoptimiert, wenn diese nicht "genutzt" werden? Das heißt, bei Basisklasen, die auch Subobjekte sind, darf man das - hier nicht?
-
shared_disadvantage schrieb:
shared_disadvantage schrieb:
Stichwort EBO.
Bzw. optimal wäre
tuple<T*, Deleter>.Kaum. Genau das würde nämlich EBO unterschlagen. Tupelelemente können nicht durch unmittelbare Vererbung implementiert werden (das hätte sonst bestimmte Einschränkungen zur Folge, so könnten POD-Tuplemember nicht mehr per memcpy angefasst werden).
-
Das klingt tatsächlich doof, den der unique_ptr ist eigentlich Pflicht in modernem C++.
Das ist doch Quatsch. Hoer doch mal mit dem Dogma auf!
Benutze RAII wann immer es geht!
Macht er doch, er will sie im Destruktor freigeben ...
Wahrscheinlich meint er, weil er rohe Pointer benutzt holt er Geschwindigkeit raus.
Aber er weis nicht, was er macht daher...Aus der Luft gegriffene Unterstellung.
Den Deleter.
Der Deleter steckt normalerweise im Typ und nicht im Objekt. 2 unique_ptr vom gleichen Typ koennen keinen unterschiedlichen deleter haben.
-
Das heißt, bei Basisklasen, die auch Subobjekte sind, darf man das - hier nicht?
Hmm. Die Frage sollte sich wohl von selbst beantworten. Natürlich können die nicht optimiert werden...
unique_ptr vom gleichen Typ koennen keinen unterschiedlichen deleter haben.
Nein der Typ ihres Deleters kann nicht unterschiedlich sein, und? Was heißt das jetzt im Bezug auf den Member?
Das ist doch Quatsch.
Was ist Quatsch? Ich rede offensichtlich von den Fällen, wo ein roher Zeiger ein Objekt besitzt...
-
Was heißt das jetzt im Bezug auf den Member?
Warum sollte ich den Deleter als Member halten, wenn er fuer alle Objekte gleich ist?