Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

Architekt

Community-Fossil

  • »Architekt« ist der Autor dieses Themas

Beiträge: 2 481

Wohnort: Hamburg

Beruf: Student

  • Private Nachricht senden

1

11.05.2014, 23:31

[erledigt] eventually owning pointer

Moin zusammen.
Ich wage mich seit kurzer Zeit mal wieder an C++, nachdem ich D den Rücken gekehrt habe, und habe schon binnen weniger Tage ein kleine Frage.
Und zwar: Eine Klasse Foo benutzt eine Instanz von Bar. Derzeit handhabe ich es so, dass Foo einfach einen Raw Pointer auf Bar hält, während Bar als lvalue Referenz an Foo übergeben wird.
In etwa so:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
class Bar;

class Foo {
private:
    Bar* _b;

public:
    void setBar(Bar& b) {
        _b = &b;
    }
};

Doch es ist etwas mühselig geworden, ständig darauf zu achten, dass Foo einen Pointer auf ein lebendes Bar hält. Man muss sich ständig darum kümmern, dass das übergeben Bar Objekt die gleiche oder längere Lebenszeit hat, wie Foo.
In den meisten fällen ist das nicht schwer,aber ich habe mittlerweile ein paar mal erlebt, das es mich doch gestört hat.
Ich dachte dann zunächst, ich übergebe es by value und scheiß auf die Kopie (ist ja eh relativ billig). Eine andere Idee war, dass es mit einem eventually owning pointer geht. Gibt es so natürlich (glaube ich zumindest) nicht. Dieser "smart pointer" würde dann den Pointer sowie ein bool halten, der angibt, ob der Pointer geowned wird, oder ob er auf etwas zeigt, dass sich selbst um seine Lebenszeit kümmert. Je nachdem gibt dieser smart pointer seinen verwalteten Zeiger am Ende seines scopes frei, oder eben nicht.
Dann würde ich etwa bei Bar& b davon Ausgehen, dass sich extern um Bar gekümmert wird, während ich bei Bar&& b mich dann selbst um die Lebenszeit kümmern würde.
Ist natürlich etwas mehr Aufwand. Ich wollte einfach fragen ob jemand schon selbst so ein Problem hatte und was er dann getan hat.
Für mich ergeben sich 3 Lösungen:
  1. Es so lassen, Foo hält nur einen Raw Pointer auf Bar und man sieht zu, dass Bar eben mindestens genauso lange existiert
  2. By value
  3. Per eventually owning pointer

Danke.
Der einfachste Weg eine Kopie zu entfernen ist sie zu löschen.
- Stephan Schmidt -

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Architekt« (12.05.2014, 09:45)


DeKugelschieber

Community-Fossil

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

2

11.05.2014, 23:51

Früher 1, jetzt shared_ptr.

Architekt

Community-Fossil

  • »Architekt« ist der Autor dieses Themas

Beiträge: 2 481

Wohnort: Hamburg

Beruf: Student

  • Private Nachricht senden

3

11.05.2014, 23:55

Und wenn es ein Bar& ist, es also woanders eig schon existiert, habe ich dann entweder undefiniertes Verhalten wegen Stack Pointer, oder aber einen Heap Zeiger, egal ob Bar schon existierte. Das wäre ja eine pessimistische Annahme. :/
Der einfachste Weg eine Kopie zu entfernen ist sie zu löschen.
- Stephan Schmidt -

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

4

12.05.2014, 06:34

Wenn du per Stack die Lebensdauer nicht sicherstellen kannst, geht es ohne Heap eben nicht. Für mich klingt Dein Problem nach einem shared_ptr. Wobei ich allerdings nicht verstehe, warum das Objekt mal geowned werden soll und mal nicht. Klingt für mich nach schlechtem Design.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Architekt

Community-Fossil

  • »Architekt« ist der Autor dieses Themas

Beiträge: 2 481

Wohnort: Hamburg

Beruf: Student

  • Private Nachricht senden

5

12.05.2014, 09:45

Habe ich mich etwa so schlecht ausgedrückt? :hmm:
Wenn es als Bar& übergeben wird, handelt es sich logischerweise um ein lvalue, also existiert außerhalb von Foo ein Bar. Und das wird wohl noch leben. Mit Bar&& habe ich ein rvalue, also etwas, was demnächst verfällt (sobald die Funktion endet). Und in diesem Fall würde ich einen Bar Zeiger auf dem Heap erstellen in den ich das rvalue kopiere. Für den Fall, dass Bar ein lvalue ist, möchte ich es nicht besitzen, weil es ohnehin schon existiert und ein Raw Pointer darauf ausreicht. Ich muss mich nicht darum kümmern, dass es am Lebens bleibt. Doch bei einem rvalue muss ich das ja quasi. Das ist auch eher eine Frage also ein fester Design Entwurf, derzeit hält Foo eben nur einen Raw Pointer und die Lebenszeit von Bar muss extern gehandhabt werden. Ich weiß nicht wieso bei jeder kleineren Frage in diesem Forum "schlechtes" Design als präventiv Antwort einfließt. Das Forum ist wirklich kein schöner Ort mehr, an dem man einfach so eine Frage stellt, habe selbst 3 mal überlegt, ob ich wirklich hier diese Frage stellen sollte.
Ich werd mal selbst noch etwas damit experimentieren und wähle mir sonst Möglichkeit 1 oder 2 aus. Kann also geclosed werden.
Der einfachste Weg eine Kopie zu entfernen ist sie zu löschen.
- Stephan Schmidt -

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

6

12.05.2014, 13:06

Ich verstehe nicht worauf Du hinaus willst. Entweder hast Du Objekte, um deren Lebensdauer Du Dich kümmern musst oder Du hast welche, deren Lebensdauer Dich nichts angeht und nicht von Dir verwaltet werden muss. Was davon jetzt besser ist, kann man doch aber nicht pauschal entscheiden, sondern hängt von jeweiligen Anwendungsfall ab. Ich hatte das aber so verstanden, dass Du eine Methode bauen willst, die sich um beide Gegebenheiten kümmern kann und das fände ich sehr schlecht. Sie sollte fest definieren, ob sie das Objekt besitzen muss oder ob sie nur eine gültige Referenz braucht, um die sie sich aber nicht kümmert, weil ihr das Objekt nicht gehört.

Warum sollte ich den hybriden Ansatz da nicht als schlechtes Design betiteln dürfen? In einem guten Design ist immer klar, wer etwas besitzt und wer nicht. Alle anderen Aussagen lassen sich wie gesagt nicht pauschalisieren. Da weiß ich auch gar nicht, was das mit "präventiver Antwort" oder "das Forum ist unschöner Ort" zu tun hat.

Mal brauchst Du das eine, mal das andere. Mal eine Kopie, mal eine Referenz, mal einen Raw-Pointer. Mal als Owner und mal nicht. Eine eierlegende-Wollmilchsau-Lösung finde ich da äußerst unschön.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

7

12.05.2014, 13:27

Da muss ich BlueCobold aber recht geben. Für mich wirkt es auch eher als wenn dein Design dahinter nicht besonders schön ist. Ich verstehe auch nicht ganz warum die Methode pauschal beides können soll. Vielleicht wäre es aber auch gut wenn du ein konkretes Beispiel zeigen würdest. Foo und Bar ist ja nicht ganz nah an der Realität. Vielleicht machst du dir auch Gedanken über ein Problem was du so nicht kriegen würdest. Versuch das ganze vielleicht noch mal zu konkretisieren.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

DeKugelschieber

Community-Fossil

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

8

12.05.2014, 13:38

Den shared_ptr würdest du ja auch by copy übergeben:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
class Foo{}

class Bar{
    private:
        shared_ptr<Foo> foo;

    public:
        Bar(const shared_ptr<Foo> foo):foo(foo){}
}


z.B....

Architekt

Community-Fossil

  • »Architekt« ist der Autor dieses Themas

Beiträge: 2 481

Wohnort: Hamburg

Beruf: Student

  • Private Nachricht senden

9

12.05.2014, 13:40

Es ging mir viel mehr um den theoretischen Aspekt. Mein Design ist ja momentan so aufgebaut, dass Foo nur einen Raw Pointer hält, also nicht dafür zuständig ist. Denke dabei werde ich es auch belassen. Aber ja, dann hast du es richtig verstanden, ich wollte, dass Foo sich abhängig von der Übergabe entweder selbst um Bar kümmert, oder nicht.
Der einfachste Weg eine Kopie zu entfernen ist sie zu löschen.
- Stephan Schmidt -

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

10

12.05.2014, 13:50

Wenn dein Foo ein Bar benutzt und dieses Bar aber vor dem Foo zerstört werden kann, dann hast du ein ganz ganz ganz grundlegendes Problem in deinem Design und solltest – wenn du mich fragst – besser dieses Problem fixen, anstatt mit irgendwelchen Laufzeitmechanismen die Symptome zu bekämpfen. ;)

Der Unterschied zwischen "Objekt A besitzt Objekt B" und "Objekt A verwendet Objekt B" ist dermaßen fundamentaler Natur, ich sehe nicht, inwiefern es Sinn machen würde, in der selben Klasse beide Fälle zu handhaben, insbesondere nicht dynamisch. Kannst du vielleicht ein Beispiel dafür geben, wo du so etwas angebracht finden würdest?

Werbeanzeige