Wie die Lebensdauer der lokalen Variablen verlängert wird oder wie man Referenzen richtig einsetzt

8

Ich habe eine Klasse entwickelt und bin auf diese Frage gestoßen. Überlege, dass ich folgende Klasse habe:

%Vor%

Und folgende Klasse mit A als Eigenschaft:

%Vor%

Und diese Funktion, die nach einem variablen Wert sucht und verschiedene Objekte in verschiedenen Fällen zurückgibt:

%Vor%

Nun möchte ich diese Funktion wie folgt verwenden:

%Vor%

Der Zweck dieser Situation ist:

Funktion foo sollte zurückgeben (oder verschieben), ohne ein lokales Objekt mit Änderungen in p zu kopieren, wenn das Argument true ist, oder sollte die Eigenschaft der globalen Variablen temp ohne Aufruf von Kopierkonstruktoren von A ( dh Rückgabewert von myList ) und auch nicht myList von B (es sollte nicht myList von B zerstören, also std::move kann nicht verwendet werden), wenn das Argument false ist.

Meine Frage ist:

Wie soll ich die Funktion foo ändern, um den oberen Bedingungen zu folgen? Die aktuelle Implementierung von foo funktioniert in true case und verschiebt diese lokale Variable, aber für den Fall false wird der Kopierkonstruktor für list2 aufgerufen. Eine andere Idee war, die Lebensdauer der lokalen Variablen irgendwie zu verlängern, aber das Hinzufügen von const-Referenz funktionierte nicht für mich. Aktuelle Ausgabe ist:

%Vor%     
Egor Schavelev 21.07.2017, 08:45
quelle

3 Antworten

3

Wenn Sie B zu

ändern können %Vor%

dann foo kann sein:

%Vor%

Demo

Ausgabe ist

%Vor%     
Jarod42 21.07.2017, 11:38
quelle
2

Die einfachste Lösung ist wahrscheinlich die Verwendung von std::shared_ptr wie in Jarod42s Antwort. Aber wenn Sie Smart Pointer vermeiden wollen oder wenn Sie B nicht ändern können, können Sie wahrscheinlich Ihre eigene Wrapper-Klasse erstellen, die möglicherweise ein A besitzt oder nicht. std::optional könnte dafür sehr praktisch sein:

%Vor%

Die Klasse enthält optional , um das A zu besitzen, falls erforderlich, und Sie können move-semantics verwenden, um sie zu verschieben. Die Klasse enthält auch einen Verweis (oder Zeiger), der entweder auf den enthaltenen Wert verweist oder auf ein anderes Objekt verweist .

Sie können dies von foo :

zurückgeben %Vor%

Und der Aufrufer kann auf die enthaltene Referenz zugreifen:

%Vor%

Live-Demo .

Wenn Sie keinen Zugriff auf std::optional haben, gibt es boost::optional oder Sie könnten std::unique_ptr auf Kosten einer dynamischen Speicherzuweisung verwenden.

    
Chris Drew 21.07.2017 14:44
quelle
0

Ihre Funktion foo gibt eine Instanz von A zurück, keine Referenz (oder einen Zeiger), sodass Sie keinen Zugriff auf B.myList Inhalt ohne zu kopieren oder zu verschieben.

Um diesen Zugang zu haben, sollten Sie entweder intelligente Zeiger (wie Jarod42) verwenden oder einfach nur solche Zeiger:

%Vor%

Allerdings wird dieser spezielle Code nicht funktionieren. coz .getList () gibt const zurück, aber foo gibt einen nicht-konstanten Zeiger zurück (dies könnte, sollte aber nicht schmutzig sein, gehackt mit const_cast & lt ; & gt;).

Im Allgemeinen müssen Sie auswählen, was genau die Funktion foo zurückgeben soll:

  • neue Instanz der A -Klasse mit spezifischen Daten
  • Zugriff auf vorhandene Instanz

Wenn Sie diese Entscheidung zur Laufzeit treffen müssen (zum Beispiel mit Ihrem bool-Parameter), dann sind die Zeiger (einfach oder intelligent - was auch immer) die einzige Option (vergessen Sie auch nicht, manuell zugewiesenen Speicher zu löschen).

    
Gleb 21.07.2017 12:02
quelle