RAI vs std::unique_ptr
-
@Steffo sagte in RAI vs std::unique_ptr:
hätte mit RAI alles abgedeckt.
Du hättest schon die 5er Regel nicht erfüllt.
-
Dieser Beitrag wurde gelöscht!
-
@Steffo sagte in RAI vs std::unique_ptr:
Ich sehe da sogar Nachteile, da bei Vorwärtsdeklarationen auch noch eine Funktion für das Delete mitgegeben werden muss,
Den Satz verstehe ich nicht.
-
@manni66
Steffo braucht noch ein bisschem um die Frage umzuformulieren oder bis er sich klar darüber ist das er in seinem Projekten ganz viele Memory-Leaks hat
-
@Steffo sagte in RAI vs std::unique_ptr:
Ich weiß nicht, ob wir vom selben Reden. Im obigen Beispiel hätte ich bla_instance als Roh-Pointer nehmen können und hätte mit RAI alles abgedeckt. Ein std::unique_ptr wäre vollkommen unnötig gewesen. Wozu nehmen hier manche std::unique_ptr?
Wegen dem Single Responsibility Principle -- eine Klasse sollte nur eine Aufgabe haben. Deine Klasse hat zusätzlich zu ihrer eigentlichen Aufgabe noch die Aufgabe, eine Resource zu verwalten. Mit unique_ptr übernimmt das eine andere Klasse.
Es heißt übrigens RAII.
-
Hier mal ein vollständiges Beispiel, wie man das mit RAI macht:
class foo { public: foo() { bla = new bla(); } ~foo() { delete bla; } private: bla* bla_instance; }
Zurück zu meiner Ausgangsfrage
Wozu std::unique_ptr?
-
foo f1; foo f2; f1 = f2; // Bumm
-
Das ist aber kein RAII - weil du deinen Speicher "von Hand" aufräumst
Online-Testen: cpp.sh/4w6ds
#include <iostream> #include <memory> struct test { test(){ std::cout << "test.ctor" << std::endl; } ~test(){ std::cout << "test.dtor" << std::endl; } }; struct test2 { test2():t(new test()){} std::unique_ptr<test> t; }; struct test3 { test3():t(new test()){} test* t; }; int main() { test2(); test3(); }
Ausgabe:
test.ctor
test.dtor
test.ctor
-
Naja, er macht schon sowas wie RAII. Nur halt manuell und unvollständig. Wenn er das fehlerfrei und vollständig komplettiert hat er aber genau das, was
std::unique_ptr
macht. Und dann kann man sich natürlich fragen, warum man den nicht sofort benutzt hat.
-
@llm sagte in RAI vs std::unique_ptr:
Das ist aber kein RAII - weil du deinen Speicher "von Hand" aufräumst
Online-Testen: cpp.sh/4w6ds
#include <iostream> #include <memory> struct test { test(){ std::cout << "test.ctor" << std::endl; } ~test(){ std::cout << "test.dtor" << std::endl; } }; struct test2 { test2():t(new test()){} std::unique_ptr<test> t; }; struct test3 { test3():t(new test()){} test* t; }; int main() { test2(); test3(); }
Ausgabe:
test.ctor
test.dtor
test.ctortest3 hat ja auch ein Leak. Bevor es std::unique_ptr gab, ist man doch genau so vorgegangen und nannte das RAII, oder nicht?
-
Klar - aber der unique_ptr forciert das RAII Konzept für Heap-Dinge
-
@manni66 sagte in RAI vs std::unique_ptr:
foo f1; foo f2; f1 = f2; // Bumm
Nicht wirklich: http://cpp.sh/8rzfo
-
@Steffo sagte in RAI vs std::unique_ptr:
Nicht wirklich:
Doch wirklich. Memory leak und double free.
-
@manni66 sagte in RAI vs std::unique_ptr:
@Steffo sagte in RAI vs std::unique_ptr:
Ich sehe da sogar Nachteile, da bei Vorwärtsdeklarationen auch noch eine Funktion für das Delete mitgegeben werden muss,
Den Satz verstehe ich nicht.
Das hier funktioniert nicht.
// Vorwärtsdeklaration class bla; class foo { public: foo(); // Instanziierung von Member-Variablen ~foo(); // Bei Raw-Pointern wird hier delete gemacht private: std::unique_ptr<bla> bla_instance; }
-
-
@manni66 sagte in RAI vs std::unique_ptr:
@Steffo
In die cppfoo::~foo() = default;
und schon geht's.
Ich kann dir wirklich nicht folgen. Es kompiliert und der Konstruktor wird zwei mal aufgerufen:
-
@Steffo sagte in RAI vs std::unique_ptr:
@manni66 sagte in RAI vs std::unique_ptr:
@Steffo
In die cppfoo::~foo() = default;
und schon geht's.
Ich kann dir wirklich nicht folgen. Es kompiliert und der Konstruktor wird zwei mal aufgerufen:
was hat das mit dem zitierten Code zu tun?
@manni66 sagte in RAI vs std::unique_ptr:
Doch wirklich. Memory leak und double free.
Wo kommt hier "Konstruktor wird nicht aufgerufen" vor?
Siehe auch http://cpp.sh/7hjid
-
@Steffo: Sieh dir mal die Ausgabe von
t
an: dein Code mit erweiterter AusgabeVllt. verstehst du jetzt, daß du so auch den Zuweisungsoperator
=
manuell erstellen mußt?
-
@Th69
Mit std::unique_ptr habe ich das Problem nicht?
Ich werde mir das mal nach der Arbeit genauer anschauen. Danke vorab erst mal.
-
@Steffo
Mitunique_ptr
hast du ein anderes Problem: Er ist nicht kopierbar, d.h. du musst die Kopierkonstuktoren und Zuweisungsoperatoren implementieren. Wobei.... die move-Semantik funktioniert dankunique_ptr
automatisch, die Kopiersemantik aber nicht.