it-swarm.com.de

Was ist ein Smart Pointer und wann sollte ich einen verwenden?

Was ist ein Smart Pointer und wann sollte ich einen verwenden?

1679
Alex Reynolds

UPDATE

Diese Antwort ist ziemlich alt und beschreibt, was zu dieser Zeit „gut“ war, was intelligente Zeiger waren, die von der Boost-Bibliothek bereitgestellt wurden. Seit C++ 11 verfügt die Standardbibliothek über genügend Smart Pointertypen. Daher sollten Sie die Verwendung von std::unique_ptr , std::shared_ptr und bevorzugen std::weak_ptr .

Es gab auch std::auto_ptr . Es war sehr ähnlich wie ein Bereichszeiger, außer dass es auch die "besondere" gefährliche Fähigkeit hatte, kopiert zu werden - was auch unerwartet das Eigentum überträgt.
In C++ 11 war es veraltet und in C++ 17 wurde es entfernt , daher sollten Sie es nicht verwenden.

_std::auto_ptr<MyObject> p1 (new MyObject());
std::auto_ptr<MyObject> p2 = p1; // Copy and transfer ownership. 
                                 // p1 gets set to empty!
p2->DoSomething(); // Works.
p1->DoSomething(); // Oh oh. Hopefully raises some NULL pointer exception.
_

ALTE ANTWORT

Ein Smart Pointer ist eine Klasse, die einen 'rohen' (oder 'nackten') C++ - Zeiger umschließt, um die Lebensdauer des Objekts zu verwalten, auf das verwiesen wird. Es gibt keinen einzelnen Smart Pointer-Typ, aber alle versuchen, einen rohen Zeiger auf praktische Weise zu abstrahieren.

Intelligente Zeiger sollten rohen Zeigern vorgezogen werden. Wenn Sie der Meinung sind, dass Sie Zeiger verwenden müssen (überlegen Sie zuerst, ob Sie wirklich tun), möchten Sie normalerweise einen intelligenten Zeiger verwenden, da dies viele der Probleme mit rohen Zeigern lindern kann. hauptsächlich vergessen, das Objekt zu löschen und Speicher zu verlieren.

Bei rohen Zeigern muss der Programmierer das Objekt explizit zerstören, wenn es nicht mehr nützlich ist.

_// Need to create the object to achieve some goal
MyObject* ptr = new MyObject(); 
ptr->DoSomething(); // Use the object in some way
delete ptr; // Destroy the object. Done with it.
// Wait, what if DoSomething() raises an exception...?
_

Ein intelligenter Zeiger definiert im Vergleich eine Richtlinie, wann das Objekt zerstört wird. Sie müssen das Objekt immer noch erstellen, müssen sich aber nicht mehr darum kümmern, es zu zerstören.

_SomeSmartPtr<MyObject> ptr(new MyObject());
ptr->DoSomething(); // Use the object in some way.

// Destruction of the object happens, depending 
// on the policy the smart pointer class uses.

// Destruction would happen even if DoSomething() 
// raises an exception
_

Die einfachste verwendete Richtlinie betrifft den Bereich des Smart-Pointer-Wrapper-Objekts, z. B. implementiert durch boost::scoped_ptr oder std::unique_ptr .

_void f()
{
    {
       std::unique_ptr<MyObject> ptr(new MyObject());
       ptr->DoSomethingUseful();
    } // ptr goes out of scope -- 
      // the MyObject is automatically destroyed.

    // ptr->Oops(); // Compile error: "ptr" not defined
                    // since it is no longer in scope.
}
_

Beachten Sie, dass _std::unique_ptr_ -Instanzen nicht kopiert werden können. Dies verhindert, dass der Zeiger mehrmals (falsch) gelöscht wird. Sie können jedoch Verweise darauf an andere von Ihnen aufgerufene Funktionen weitergeben.

_std::unique_ptr_ sind nützlich, wenn Sie die Lebensdauer des Objekts an einen bestimmten Codeblock binden möchten oder wenn Sie es als Elementdaten in ein anderes Objekt eingebettet haben, die Lebensdauer des anderen Objekts. Das Objekt existiert, bis der enthaltende Codeblock verlassen wird oder bis das enthaltende Objekt selbst zerstört wird.

Eine komplexere Richtlinie für intelligente Zeiger umfasst das Referenzzählen des Zeigers. Dadurch kann der Zeiger kopiert werden. Wenn der letzte "Verweis" auf das Objekt zerstört wird, wird das Objekt gelöscht. Diese Richtlinie wird von boost::shared_ptr und std::shared_ptr implementiert.

_void f()
{
    typedef std::shared_ptr<MyObject> MyObjectPtr; // Nice short alias
    MyObjectPtr p1; // Empty

    {
        MyObjectPtr p2(new MyObject());
        // There is now one "reference" to the created object
        p1 = p2; // Copy the pointer.
        // There are now two references to the object.
    } // p2 is destroyed, leaving one reference to the object.
} // p1 is destroyed, leaving a reference count of zero. 
  // The object is deleted.
_

Referenzzähler sind sehr nützlich, wenn die Lebensdauer Ihres Objekts viel komplizierter ist und nicht direkt an einen bestimmten Codeabschnitt oder an ein anderes Objekt gebunden ist.

Es gibt einen Nachteil bei Zeigern mit Referenzzählung - die Möglichkeit, eine baumelnde Referenz zu erstellen:

_// Create the smart pointer on the heap
MyObjectPtr* pp = new MyObjectPtr(new MyObject())
// Hmm, we forgot to destroy the smart pointer,
// because of that, the object is never destroyed!
_

Eine andere Möglichkeit ist das Erstellen von Zirkelverweisen:

_struct Owner {
   std::shared_ptr<Owner> other;
};

std::shared_ptr<Owner> p1 (new Owner());
std::shared_ptr<Owner> p2 (new Owner());
p1->other = p2; // p1 references p2
p2->other = p1; // p2 references p1

// Oops, the reference count of of p1 and p2 never goes to zero!
// The objects are never destroyed!
_

Um dieses Problem zu umgehen, haben sowohl Boost als auch C++ 11 einen _weak_ptr_ definiert, um einen schwachen (nicht gezählten) Verweis auf einen _shared_ptr_ zu definieren.

1811
Lloyd

Hier ist eine einfache Antwort für diese Tage des modernen C++:

  • Was ist ein Smart Pointer?
    Dies ist ein Typ, dessen Werte wie Zeiger verwendet werden können, der jedoch die zusätzliche Funktion der automatischen Speicherverwaltung bietet: Wenn ein intelligenter Zeiger nicht mehr verwendet wird, wird die Zuordnung des Speichers aufgehoben (siehe auch die detailliertere Definition auf Wikipedia ).
  • Wann sollte ich eins verwenden?
    In Code, der das Verfolgen des Eigentums an einem Teil des Speichers, das Zuweisen oder Aufheben der Zuweisung umfasst; Der Smart Pointer erspart Ihnen oft die Notwendigkeit, diese Dinge explizit zu tun.
  • Aber welchen intelligenten Zeiger soll ich in welchem ​​dieser Fälle verwenden?
    • Verwenden Sie std::unique_ptr , wenn Sie nicht beabsichtigen, mehrere Verweise auf dasselbe Objekt zu speichern. Verwenden Sie ihn beispielsweise für einen Zeiger auf den Speicher, der beim Eintreten in einen Bereich zugewiesen und beim Verlassen des Bereichs freigegeben wird.
    • Verwenden Sie std::shared_ptr , wenn Sie von mehreren Stellen auf Ihr Objekt verweisen möchten - und nicht möchten, dass die Zuordnung Ihres Objekts aufgehoben wird, bis alle diese Verweise selbst verschwunden sind.
    • Verwenden Sie std::weak_ptr , wenn Sie von mehreren Stellen aus auf Ihr Objekt verweisen möchten - für Referenzen, bei denen es in Ordnung ist, das Objekt zu ignorieren und die Zuordnung aufzuheben versuchen zu dereferenzieren).
    • Verwenden Sie die intelligenten Zeiger _boost::_ oder _std::auto_ptr_ nur in Sonderfällen, die Sie nachlesen können, wenn Sie müssen.
  • Hey, ich habe nicht gefragt, welchen ich verwenden soll!
    Ah, aber du wolltest es wirklich zugeben.
  • Wann sollte ich dann reguläre Zeiger verwenden?
    Meistens in Code, der den Besitz des Speichers nicht berücksichtigt. Dies ist in der Regel bei Funktionen der Fall, die einen Zeiger von einer anderen Stelle abrufen und keine Kopie des Zeigers zuweisen oder freigeben und keine Kopie des Zeigers speichern, die ihre Ausführung überdauert.
252
einpoklum

Smart Pointer ist ein zeigerähnlicher Typ mit einigen zusätzlichen Funktionen, z. automatische Speicherfreigabe, Referenzzählung etc.

Ein kleines Intro finden Sie auf Seite Smart Pointers - What, Why, Which? .

Einer der einfachen Smart-Pointer-Typen ist std::auto_ptr (Kapitel 20.4.5 des C++ - Standards), der die automatische Freigabe von Speicher ermöglicht, wenn dieser außerhalb des Gültigkeitsbereichs liegt, und der robuster als ein einfacher Zeiger ist Verwendung, wenn Ausnahmen ausgelöst werden, obwohl weniger flexibel.

Ein weiterer praktischer Typ ist boost::shared_ptr , der die Referenzzählung implementiert und den Speicher automatisch freigibt, wenn keine Referenzen auf das Objekt verbleiben. Dies hilft, Speicherverluste zu vermeiden und ist einfach zu implementieren RAII .

Das Thema wird in Buch "C++ - Vorlagen: Der vollständige Leitfaden" von David Vandevoorde, Nicolai M. Josuttis , Kapitel 20. Smart Pointers ausführlich behandelt. Einige behandelte Themen:

107
sergtk

Die Definitionen von Chris, Sergdev und Llyod sind korrekt. Ich bevorzuge jedoch eine einfachere Definition, um mein Leben einfach zu halten: Ein intelligenter Zeiger ist einfach eine Klasse, die die Operatoren _->_ und _*_ überlädt. Das bedeutet, dass Ihr Objekt semantisch wie ein Zeiger aussieht, Sie es aber auf eine coolere Art und Weise machen können, einschließlich Referenzzählung, automatischer Zerstörung usw. _shared_ptr_ und _auto_ptr_ sind in den meisten Fällen ausreichend, gehen aber mit ihnen einher eigene Reihe kleiner Eigenheiten.

39
Sridhar Iyer

Ein intelligenter Zeiger ist wie ein normaler (typisierter) Zeiger wie "char *", außer wenn der Zeiger selbst den Gültigkeitsbereich verlässt, wird auch das gelöscht, auf das er zeigt. Sie können es wie einen normalen Zeiger verwenden, indem Sie "->" verwenden, jedoch nicht, wenn Sie einen tatsächlichen Zeiger auf die Daten benötigen. Dafür können Sie "& * ptr" verwenden.

Es ist nützlich für:

  • Objekte, die mit new belegt werden müssen, die aber die gleiche Lebensdauer wie etwas auf diesem Stapel haben sollen. Wenn das Objekt einem intelligenten Zeiger zugewiesen ist, werden sie gelöscht, wenn das Programm diese Funktion/diesen Block verlässt.

  • Datenelemente von Klassen, so dass beim Löschen des Objekts auch alle zugehörigen Daten ohne speziellen Code im Destruktor gelöscht werden (Sie müssen sicherstellen, dass der Destruktor virtuell ist, was fast immer eine gute Sache ist) .

Sie können keinen intelligenten Zeiger verwenden, wenn:

  • ... der Zeiger sollte eigentlich nicht die Daten besitzen ... d. h., wenn Sie nur die Daten verwenden, aber Sie möchten, dass sie die Funktion überleben, auf die Sie verweisen.
  • ... der Smart Pointer selbst wird nicht irgendwann zerstört. Sie möchten nicht, dass es sich in einem Speicher befindet, der niemals zerstört wird (z. B. in einem Objekt, das dynamisch zugewiesen, aber nicht explizit gelöscht wird).
  • ... zwei intelligente Zeiger möglicherweise auf dieselben Daten verweisen. (Es gibt jedoch noch intelligentere Zeiger, die damit umgehen ... das heißt Referenzzählung .)

Siehe auch:

28
markets

Die meisten Arten von intelligenten Zeigern erledigen die Entsorgung des Zeigerobjekts für Sie. Dies ist sehr praktisch, da Sie nicht mehr über das manuelle Entsorgen von Objekten nachdenken müssen.

Die am häufigsten verwendeten intelligenten Zeiger sind std::tr1::shared_ptr (oder boost::shared_ptr) und seltener std::auto_ptr. Ich empfehle die regelmäßige Verwendung von shared_ptr.

shared_ptr ist sehr vielseitig und behandelt eine Vielzahl von Entsorgungsszenarien, einschließlich Fällen, in denen Objekte "über DLL Grenzen hinweg" übergeben werden müssen (der häufigste Albtraumfall, wenn unterschiedliche libcs vorliegen) zwischen Ihrem Code und den DLLs verwendet).

16

Ein Smart Pointer ist ein Objekt, das sich wie ein Zeiger verhält, aber zusätzlich Kontrolle über Konstruktion, Zerstörung, Kopieren, Verschieben und Dereferenzieren bietet.

Man kann seinen eigenen Smart Pointer implementieren, aber viele Bibliotheken bieten auch Smart Pointer-Implementierungen mit jeweils unterschiedlichen Vor- und Nachteilen.

Beispielsweise bietet Boost die folgenden Implementierungen für intelligente Zeiger:

  • shared_ptr<T> ist ein Zeiger auf T, der einen Referenzzähler verwendet, um zu bestimmen, wann das Objekt nicht mehr benötigt wird.
  • scoped_ptr<T> ist ein Zeiger, der automatisch gelöscht wird, wenn er den Gültigkeitsbereich verlässt. Eine Zuordnung ist nicht möglich.
  • intrusive_ptr<T> ist ein weiterer Referenzzähler. Es bietet eine bessere Leistung als shared_ptr, erfordert jedoch den Typ T, um einen eigenen Referenzzählmechanismus bereitzustellen.
  • weak_ptr<T> ist ein schwacher Zeiger, der mit shared_ptr zusammenarbeitet, um Zirkelverweise zu vermeiden.
  • shared_array<T> ist wie shared_ptr, aber für Arrays von T.
  • scoped_array<T> ist wie scoped_ptr, aber für Arrays von T.

Dies sind jeweils nur eine lineare Beschreibung und können je nach Bedarf verwendet werden. Weitere Details und Beispiele finden Sie in der Dokumentation von Boost.

Darüber hinaus bietet die C++ - Standardbibliothek drei intelligente Zeiger. std::unique_ptr für eindeutiges Eigentum, std::shared_ptr für gemeinsames Eigentum und std::weak_ptr. std::auto_ptr existierte in C++ 03, ist aber jetzt veraltet.

16
Saqlain

Hier der Link für ähnliche Antworten: http://sickprogrammersarea.blogspot.in/2014/03/technical-interview-questions-on-c_6.html

Ein Smart Pointer ist ein Objekt, das wie ein normaler Zeiger wirkt, aussieht und sich anfühlt, aber mehr Funktionalität bietet. In C++ werden intelligente Zeiger als Vorlagenklassen implementiert, die einen Zeiger einschließen und Standardzeigeroperatoren überschreiben. Sie haben eine Reihe von Vorteilen gegenüber regulären Zeigern. Sie werden garantiert entweder als Nullzeiger oder als Zeiger auf ein Heap-Objekt initialisiert. Die Indirektion durch einen Nullzeiger wird geprüft. Es ist niemals ein Löschen erforderlich. Objekte werden automatisch freigegeben, wenn der letzte Zeiger auf sie verschwunden ist. Ein wesentliches Problem bei diesen intelligenten Zeigern ist, dass sie im Gegensatz zu regulären Zeigern die Vererbung nicht respektieren. Intelligente Zeiger sind für polymorphen Code nicht attraktiv. Nachfolgend finden Sie ein Beispiel für die Implementierung von Smart Pointern.

Beispiel:

template <class X>
class smart_pointer
{
          public:
               smart_pointer();                          // makes a null pointer
               smart_pointer(const X& x)            // makes pointer to copy of x

               X& operator *( );
               const X& operator*( ) const;
               X* operator->() const;

               smart_pointer(const smart_pointer <X> &);
               const smart_pointer <X> & operator =(const smart_pointer<X>&);
               ~smart_pointer();
          private:
               //...
};

Diese Klasse implementiert einen intelligenten Zeiger auf ein Objekt vom Typ X. Das Objekt selbst befindet sich auf dem Heap. So verwenden Sie es:

smart_pointer <employee> p= employee("Harris",1333);

Wie andere überladene Operatoren verhält sich p wie ein regulärer Zeiger.

cout<<*p;
p->raise_salary(0.5);
10
Santosh

http://en.wikipedia.org/wiki/Smart_pointer

In der Informatik ist ein intelligenter Zeiger ein abstrakter Datentyp, der einen Zeiger simuliert und gleichzeitig zusätzliche Funktionen wie die automatische Speicherbereinigung oder die Grenzwertprüfung bereitstellt. Diese zusätzlichen Funktionen sollen Fehler reduzieren, die durch den Missbrauch von Zeigern verursacht werden, während die Effizienz erhalten bleibt. Intelligente Zeiger verfolgen normalerweise die Objekte, die zum Zwecke der Speicherverwaltung auf sie zeigen. Der Missbrauch von Zeigern ist eine Hauptursache für Fehler: Die ständige Zuordnung, Freigabe und Referenzierung, die von einem mit Zeigern geschriebenen Programm durchgeführt werden muss, macht es sehr wahrscheinlich, dass Speicherlecks auftreten. Intelligente Zeiger versuchen, Speicherverluste zu verhindern, indem sie die automatische Freigabe der Ressource veranlassen: Wenn der Zeiger auf ein Objekt (oder auf das letzte in einer Reihe von Zeigern) zerstört wird, z.

8
Jorge Ferreira

Sei T eine Klasse in diesem Tutorial. Zeiger in C++ können in drei Typen unterteilt werden:

1) Rohzeiger :

T a;  
T * _ptr = &a; 

Sie enthalten eine Speicheradresse an einer Stelle im Speicher. Seien Sie vorsichtig, da es schwierig wird, Programme zu verwalten.

Zeiger mit konstanten Daten oder Adressen {Rückwärts lesen}

T a ; 
const T * ptr1 = &a ; 
T const * ptr1 = &a ;

Zeiger auf einen Datentyp T, der eine Konstante ist. Das heißt, Sie können den Datentyp nicht mit dem Zeiger ändern. dh *ptr1 = 19; wird nicht funktionieren. Sie können den Zeiger jedoch bewegen. dh ptr1++ , ptr1--; etc wird funktionieren. Rückwärts lesen: Zeiger auf Typ T, der const ist

  T * const ptr2 ;

Ein const-Zeiger auf einen Datentyp T. Das heißt, Sie können den Zeiger nicht bewegen, aber Sie können den Wert ändern, auf den der Zeiger zeigt. dh *ptr2 = 19 wird funktionieren, aber ptr2++ ; ptr2-- etc wird nicht funktionieren. Rückwärts lesen: const Zeiger auf einen Typ T

const T * const ptr3 ; 

Ein const-Zeiger auf einen const-Datentyp T. Das heißt, Sie können weder den Zeiger verschieben noch den Datentypzeiger in den Zeiger ändern. dh ptr3-- ; ptr3++ ; *ptr3 = 19; funktioniert nicht

3) Smart Pointer : {#include <memory>}

Shared Pointer :

  T a ; 
     //shared_ptr<T> shptr(new T) ; not recommended but works 
     shared_ptr<T> shptr = make_shared<T>(); // faster + exception safe

     std::cout << shptr.use_count() ; // 1 //  gives the number of " 
things " pointing to it. 
     T * temp = shptr.get(); // gives a pointer to object

     // shared_pointer used like a regular pointer to call member functions
      shptr->memFn();
     (*shptr).memFn(); 

    //
     shptr.reset() ; // frees the object pointed to be the ptr 
     shptr = nullptr ; // frees the object 
     shptr = make_shared<T>() ; // frees the original object and points to new object

Implementiert mit Referenzzählung, um zu verfolgen, wie viele "Dinge" auf das Objekt zeigen, auf das der Zeiger zeigt. Wenn dieser Zähler auf 0 geht, wird das Objekt automatisch gelöscht, dh objected wird gelöscht, wenn alle share_ptr, die auf das Objekt zeigen, den Gültigkeitsbereich verlassen. Das erspart Ihnen das Löschen von Objekten, die Sie mit new zugewiesen haben.

Schwacher Zeiger: Hilft beim Umgang mit zyklischen Verweisen, die bei der Verwendung von gemeinsam genutzten Zeigern auftreten, wenn Sie zwei Objekte haben, auf die von zwei gemeinsam genutzten Zeigern verwiesen wird, und es einen internen gemeinsam genutzten Zeiger gibt Wenn Sie auf den gemeinsam genutzten Zeiger des anderen Zeigers zeigen, wird eine zyklische Referenz erstellt und das Objekt wird nicht gelöscht, wenn freigegebene Zeiger den Gültigkeitsbereich verlassen. Ändern Sie das interne Mitglied von einem shared_ptr zu einem weak_ptr, um dieses Problem zu beheben. Hinweis: Um auf das Element zuzugreifen, auf das ein schwacher Zeiger zeigt, verwenden Sie lock (). Dies gibt einen weak_ptr zurück.

T a ; 
shared_ptr<T> shr = make_shared<T>() ; 
weak_ptr<T> wk = shr ; // initialize a weak_ptr from a shared_ptr 
wk.lock()->memFn() ; // use lock to get a shared_ptr 
//   ^^^ Can lead to exception if the shared ptr has gone out of scope
if(!wk.expired()) wk.lock()->memFn() ;
// Check if shared ptr has gone out of scope before access

Siehe: Wann ist std :: weak_ptr sinnvoll?

Einzigartiger Zeiger: Leichter intelligenter Zeiger mit exklusivem Eigentum. Wird verwendet, wenn der Zeiger auf eindeutige Objekte zeigt, ohne die Objekte zwischen den Zeigern zu teilen.

unique_ptr<T> uptr(new T);
uptr->memFn(); 

//T * ptr = uptr.release(); // uptr becomes null and object is pointed to by ptr
uptr.reset() ; // deletes the object pointed to by uptr 

Verwenden Sie die Verschiebungssemantik, um das Objekt zu ändern, auf das der eindeutige ptr zeigt

unique_ptr<T> uptr1(new T);
unique_ptr<T> uptr2(new T);
uptr2 = std::move(uptr1); 
// object pointed by uptr2 is deleted and 
// object pointed by uptr1 is pointed to by uptr2
// uptr1 becomes null 

Referenzen: Sie können im Wesentlichen als const-Zeiger verstanden werden, dh als Zeiger, der const ist und nicht mit einer besseren Syntax verschoben werden kann.

Siehe: Was sind die Unterschiede zwischen einer Zeigervariablen und einer Referenzvariablen in C++?

r-value reference : reference to a temporary object   
l-value reference : reference to an object whose address can be obtained
const reference : reference to a data type which is const and cannot be modified 

Hinweis: https://www.youtube.com/channel/UCEOGtxYTB6vo6MQ-WQ9W_nQ Vielen Dank an Andre, der auf diese Frage hingewiesen hat.

5
nnrales

Ein Smart Pointer ist eine Klasse, ein Wrapper eines normalen Zeigers. Im Gegensatz zu normalen Zeigern basiert der Lebenszyklus von Smart Points auf einem Referenzzähler (wie oft das Smart-Pointer-Objekt zugewiesen wurde). Wenn also ein Smart Pointer einem anderen zugewiesen wird, zählt der interne Verweis plus plus. Und wenn das Objekt den Gültigkeitsbereich verlässt, wird die Referenz minus minus gezählt.

Obwohl der automatische Zeiger ähnlich aussieht, unterscheidet er sich grundlegend vom intelligenten Zeiger. Es ist eine praktische Klasse, die die Zuordnung der Ressource aufhebt, wenn ein automatisches Zeigerobjekt den Gültigkeitsbereich der Variablen verlässt. In gewissem Maße funktioniert ein Zeiger (auf dynamisch zugewiesenen Speicher) ähnlich wie eine Stapelvariable (statisch zugewiesen in der Kompilierungszeit).

3
Trombe

Intelligente Zeiger sind Zeiger, bei denen Sie sich nicht um die Freigabe des Arbeitsspeichers, die gemeinsame Nutzung von Ressourcen und die Übertragung kümmern müssen.

Sie können diesen Zeiger sehr gut verwenden, ähnlich wie eine Zuordnung in Java funktioniert. In Java Garbage Collector wird der Trick ausgeführt, während in Smart Pointers der Trick von Destruktoren ausgeführt wird.

2
Daksh

Die vorhandenen Antworten sind gut, decken jedoch nicht ab, was zu tun ist, wenn ein intelligenter Zeiger nicht die (vollständige) Antwort auf das zu lösende Problem ist.

Unter anderem (in anderen Antworten gut erklärt) ist die Verwendung eines intelligenten Zeigers eine mögliche Lösung für Wie verwenden wir eine abstrakte Klasse als Funktionsrückgabetyp? , die als Duplikat dieser Frage markiert wurde. Die erste Frage, die Sie stellen müssen, wenn Sie versucht sind, eine abstrakte (oder tatsächlich eine beliebige) Basisklasse als Rückgabetyp in C++ anzugeben, lautet "Was meinen Sie wirklich?". In der Dokumentation der boost pointer container library gibt es eine gute Diskussion (mit weiteren Referenzen) über die idiomatische objektorientierte Programmierung in C++ (und wie sich diese von anderen Sprachen unterscheidet). Zusammenfassend muss man in C++ über den Besitz nachdenken. Welche intelligenten Zeiger Ihnen helfen, aber nicht die einzige Lösung oder immer eine vollständige Lösung sind (sie geben Ihnen keine polymorphe Kopie) und nicht immer eine Lösung, die Sie in Ihrer Benutzeroberfläche offenlegen möchten (und eine Funktionsrückgabe klingt schrecklich) viel wie eine Schnittstelle). Es kann beispielsweise ausreichend sein, eine Referenz zurückzugeben. In all diesen Fällen (intelligenter Zeiger, Zeigercontainer oder einfaches Zurückgeben einer Referenz) haben Sie die Rückgabe von einem Wert in eine Art Referenz geändert . Wenn Sie wirklich eine Kopie benötigen, müssen Sie möglicherweise mehr Boilerplate "idiom" hinzufügen oder in C++ über das idiomatische (oder anderweitige) OOP hinausgehen, um mit Bibliotheken wie Adobe Poly oder - einen allgemeineren Polymorphismus zu erzielen. Boost.TypeErasure .

1
da77a