Rückgabetyp einer Funktion als Smartpointer

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
Antworten
joggel

Rückgabetyp einer Funktion als Smartpointer

Beitrag von joggel »

Guten Morgen,

ich habe folgendes gegeben:
- einen std::vector als Member einer Klasse
- eine Funktion die diesen Container als smart-pointer, also nicht als Kopie, zurückgeben soll.

Es gibt ja diesen std::shared_ptr.
Kann ich nicht meinen Container in der Funktion irgendwie als diesen smart-pointer zurückgeben?

Ich meine, ich könnte ja meinen Container von Anfang an als shared_ptr deklarieren, nur irgendwie passt mir das nicht recht...
Der Eigentümer bleibt definitiv von Anfang bis Ende eben diese Klasse, ich möchte nur an einer Stelle auf diesen Container von Außen zugreifen...

Ich hoffe ihr versteht mein Problem.

Gruß
Benutzeravatar
kimmi
Moderator
Beiträge: 1405
Registriert: 26.02.2009, 09:42
Echter Name: Kim Kulling
Wohnort: Luebeck
Kontaktdaten:

Re: Rückgabetyp einer Funktion als Smartpointer

Beitrag von kimmi »

Du meinst so etwas wie:

Code: Alles auswählen

make_shared<dein_container>
Problem dabei: der shared_ptr wird die Anzahl der Referenzen für dich verwalten ausgenommen der Ownership, die deine entprechende Klasse innehält. Wenn dieser nun auf 0 geht, wird versucht, dein Container abzuräumen, ohne dass der Owner davon erfährt. Versuch doch mal std::weak_ptr: http://en.cppreference.com/w/cpp/memory/weak_ptr

Gruß Kimmi
joggel

Re: Rückgabetyp einer Funktion als Smartpointer

Beitrag von joggel »

Wunderbar, das seht gut aus!
Ich danke schon mal...
joggel

Re: Rückgabetyp einer Funktion als Smartpointer

Beitrag von joggel »

Mh... so richtig gefällt mir das auch nicht.
Ich musste da trotzdem meinen Container als shared_ptr deklarieren.

Ich mache das mal mit etwas Code deutlich:

Code: Alles auswählen

Class A
{
private:
 std::vector<Foo> mContainer;

public:
 // hier will ich nur einen smart-pointer auf den Container zurückgeben
 aSmartPtr<std::vector<Foo>> getMyContainer();
}
Jetzt könnte ich das aber auch so machen damit das mit dem weak_ptr funktioniert

Code: Alles auswählen

Class A
{
private:
 std::shared_ptr<std::vector<Foo>> mContainer;

public:
 // hier will ich nur einen smart-pointer auf den Container zurückgeben
 std::weak_ptr<std::vector<Foo>> getMyContainer();
}
Nur irgendwie habe ich dabei das Gefühl, dass das "schlechtes" Design ist, da ja eben die Klasse eigentümer bleibt.
Kann sein das mein Gefühl sich da irrt und das das eben der gängige Weg ist, so wie der 2te Code-Ausschnitt!

[edit]
Ich meine, wenn ich diesen Container niemals hinausgebe, sondern maximal nur über die einzelnen Eleme von außen iterieren möchte, dann ist es doch quatsch ihn als shared_ptr zu deklarieren, oder?
Wenn, dann würde ich sagen, das ein unique_ptr da nur als smart-pointer sinn macht...


Die Frage ist eben, wie ist denn nun der "State of the Art" dabei?
Benutzeravatar
kimmi
Moderator
Beiträge: 1405
Registriert: 26.02.2009, 09:42
Echter Name: Kim Kulling
Wohnort: Luebeck
Kontaktdaten:

Re: Rückgabetyp einer Funktion als Smartpointer

Beitrag von kimmi »

Warum willst du denn den Container herausreichen? Wenn du über den COntainer iterieren möchtest, biete in Class A doch einfach ein Interface dafür an.

Kimmi
joggel

Re: Rückgabetyp einer Funktion als Smartpointer

Beitrag von joggel »

Und wie würde so ein Interface dazu aussehen?
Benutzeravatar
dot
Establishment
Beiträge: 1745
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: Rückgabetyp einer Funktion als Smartpointer

Beitrag von dot »

Wenn du nicht den Besitz nach außen abgeben willst, dann sind Smartpointer rein prinzipiell fehl am Platz, denn der einzige Sinn von Smartpointern ist die Repräsentation von Besitzverhältnissen. Was genau willst du denn erreichen; wieso muss der Container von außen erreichbar sein?
Benutzeravatar
Sternmull
Establishment
Beiträge: 264
Registriert: 27.04.2007, 00:30
Echter Name: Til
Wohnort: Dresden

Re: Rückgabetyp einer Funktion als Smartpointer

Beitrag von Sternmull »

Für mich klingt es so als würde es auch schlichtweg eine Referenz tun. Wenn deine Klasse die Lebenszeit des Containers definieren soll, und der Nutzer der Klasse über diesen Fakt informiert ist und das auch sinnvoll so ist, dann gibt es hier keinen Bedarf für die referenzgezählte Lebenszeitverwaltung für die man Smartpointer verwendet. Wenn der Nutzer den Container nur angucken, aber nicht modifizieren soll, dann nimm eine konstante Referenz.
shared_ptr und andere Smartpointer sind nur dann sinnvoll wenn ein Objekt so lange erhalten bleiben soll bis der letzte Nutzer (also der letzte Besitzer eines shared_ptr der darauf zeigt) es nicht mehr referenziert, und nicht klar ist wer der Letzte ist. Das passiert z.B. wenn es um eine Ressource geht die von vielen Objekten geteilt wird die in beliebiger Reihenfolge (z.B. aufgrund von Nutzereingaben) zerstört werden. Also z.B. zerstörbare Einheiten in einem Spiel die alle die gleiche Textur brauchen.
Benutzeravatar
kimmi
Moderator
Beiträge: 1405
Registriert: 26.02.2009, 09:42
Echter Name: Kim Kulling
Wohnort: Luebeck
Kontaktdaten:

Re: Rückgabetyp einer Funktion als Smartpointer

Beitrag von kimmi »

So etwas in Kurzform. KAnnst nat. gern Referenzen herausgeben:

Code: Alles auswählen

class A {
  std::vector<myStruct*> m_data;

public:
  myStruct *getAt( size_t i ) const;
};
Kimmi
joggel

Re: Rückgabetyp einer Funktion als Smartpointer

Beitrag von joggel »

Okay. Soweit danke erstmal.
Das ich nicht zwingend smartpointer verwenden muss scheint mir nun auch eher sinnvoll.
Ich will mich eben mit modern c++ vertraut machen und versuch da so oft wie möglich die neuen features zu verweneen. Aber anscheinend ist das nicht immer angebracht...

Zum Hintergrund meiner Frage:
Mein Spiel hat eine klasse Spiel. Diese verwaltet UI, Resourcen und sonst noch etwas.
Dann gibt es eine Level-klasse deren eigentümer die Klasse spiel ist.
Diese Level-klasse kapselt alle spielobjekte.
Dann gibt es noch eine klasse die das zeichnen übernimmt. Deren eigentümer ist ebenfalls die Spiel-klasse.
Nun wollte ich das gerne so haben:

Code: Alles auswählen

Spiel::run()
{
 renderer.renderLevel(level)
}
Naja, und da hätte ich von ausen alle zeichenbaren objekte von Level abfragen müssen.
Das heißt, ich werds so tun....
Benutzeravatar
dot
Establishment
Beiträge: 1745
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: Rückgabetyp einer Funktion als Smartpointer

Beitrag von dot »

Ich würde wohl dem Level eine draw(renderer) Methode geben, die dann einfach selbst die entsprechenden infos an renderer.drawLevel(stuff) oder was auch immer weiterreicht. Auf diese Weise muss überhaupt nie etwas von außen abgefragt werden.

Btw: Um einen std::vector zu returnen, brauchst du keine Smartpointer. Einfach by value returnen. In C++11 wird dann eh gemoved (wenn nötig kannst du explizit moven, sollte man aber nur machen, wo es nötig ist) und ansonsten wird bei jedem guten Compiler sowieso die Copy-Elision greifen... ;)
joggel

Re: Rückgabetyp einer Funktion als Smartpointer

Beitrag von joggel »

dot hat geschrieben:Ich würde wohl dem Level eine draw(renderer) Methode geben, die dann einfach selbst die entsprechenden infos an renderer.drawLevel(stuff) oder was auch immer weiterreicht. Auf diese Weise muss überhaupt nie etwas von außen abgefragt werden.
Ja, das war jetzt zum schluss auch mein gedanke. Werd ich wohl so tun.
Antworten