Was ist ein intelligenter Zeiger und wann sollte ich einen verwenden?
Was ist ein intelligenter Zeiger und wann sollte ich einen verwenden?
Antworten:
AKTUALISIEREN
Diese Antwort ist ziemlich alt und beschreibt daher, was zu dieser Zeit „gut“ war, nämlich intelligente Hinweise, die von der Boost-Bibliothek bereitgestellt wurden. Seit C ++ 11 bietet die Standardbibliothek ausreichend Smart-Pointer-Typen. 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 einem Zeiger mit Gültigkeitsbereich sehr ähnlich, außer dass es auch die "besondere" gefährliche Fähigkeit hatte, kopiert zu werden - was auch unerwartet das Eigentum überträgt.
Es war in C ++ 11 veraltet und wurde in C ++ 17 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 intelligenter Zeiger 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 einzigen intelligenten Zeigertyp, aber alle versuchen, einen Rohzeiger auf praktische Weise zu abstrahieren.
Intelligente Zeiger sollten gegenüber rohen Zeigern bevorzugt werden. Wenn Sie der Meinung sind, dass Sie Zeiger verwenden müssen (überlegen Sie zuerst, ob Sie dies wirklich tun), möchten Sie normalerweise einen intelligenten Zeiger verwenden, da dies viele Probleme mit Rohzeigern lindern kann, hauptsächlich das 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 darüber, wann das Objekt zerstört wird. Sie müssen das Objekt 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 von 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
s 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 dieses anderen Objekts. Das Objekt existiert, bis der enthaltende Codeblock verlassen wird oder bis das enthaltende Objekt selbst zerstört wird.
Eine komplexere Smart-Pointer-Richtlinie 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 implementiert std::shared_ptr
.
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ählzeiger sind sehr nützlich, wenn die Lebensdauer Ihres Objekts viel komplizierter ist und nicht direkt an einen bestimmten Codeabschnitt oder ein anderes Objekt gebunden ist.
Es gibt einen Nachteil bei referenzgezählten Zeigern - 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 a definiert weak_ptr
, um einen schwachen (nicht gezählten) Verweis auf a zu definieren shared_ptr
.
std::auto_ptr<MyObject> p1 (new MyObject());
statt std::auto_ptr<MyObject> p1 (new Owner());
?
const std::auto_ptr
ist sicher zu verwenden, wenn Sie mit C ++ 03 nicht weiterkommen. Ich habe es ziemlich oft für Pimpl-Muster verwendet, bis ich Zugriff auf C ++ 11 bekam.
Hier ist eine einfache Antwort für diese Tage des modernen C ++ (C ++ 11 und höher):
std::unique_ptr
Sie diese Option, wenn Sie nicht mehrere Verweise auf dasselbe Objekt enthalten möchten. Verwenden Sie es beispielsweise für einen Zeiger auf den Speicher, der beim Eingeben eines Bereichs zugewiesen und beim Verlassen des Bereichs freigegeben wird.std::shared_ptr
Sie diese Option, wenn Sie von mehreren Stellen aus auf Ihr Objekt verweisen möchten - und nicht möchten, dass die Zuordnung Ihres Objekts aufgehoben wird, bis alle diese Referenzen selbst verschwunden sind.std::weak_ptr
Sie diese Option, wenn Sie von mehreren Stellen aus auf Ihr Objekt verweisen möchten - für Referenzen, für die das Ignorieren und Freigeben in Ordnung ist (sie werden also nur feststellen, dass das Objekt beim Versuch der Dereferenzierung nicht mehr vorhanden ist).boost::
intelligenten Zeiger oder std::auto_ptr
außer in besonderen Fällen, die Sie bei Bedarf nachlesen können.T*
ist zu std::unique_ptr<T>
was std::weak_ptr<T>
ist zustd::shared_ptr<T>
Smart Pointer ist ein zeigerähnlicher Typ mit einigen zusätzlichen Funktionen, z. B. automatische Speicherfreigabe, Referenzzählung usw.
Ein kleines Intro finden Sie auf Seite Smart Pointers - Was, warum, was? .
Einer der einfachen Smart-Pointer-Typen ist std::auto_ptr
(Kapitel 20.4.5 des C ++ - Standards), der es ermöglicht, Speicher automatisch freizugeben, wenn er außerhalb des Gültigkeitsbereichs liegt, und der robuster ist als die einfache Zeigerverwendung, wenn Ausnahmen ausgelöst werden, obwohl er weniger flexibel ist.
Ein weiterer praktischer Typ ist boost::shared_ptr
die Implementierung der Referenzzählung und die automatische Freigabe des Speichers, wenn keine Referenzen auf das Objekt mehr vorhanden sind. Dies hilft, Speicherlecks zu vermeiden, und ist einfach zu implementieren, um RAII zu implementieren .
Das Thema wird im Buch "C ++ - Vorlagen: Der vollständige Leitfaden" von David Vandevoorde, Nicolai M. Josuttis , Kapitel Kapitel 20 ausführlich behandelt. Intelligente Zeiger. Einige behandelte Themen:
std::auto_ptr
ist veraltet und wird dringend empfohlen, da Sie versehentlich das Eigentum übertragen können. - C ++ 11 beseitigt die Notwendigkeit von Boost, benutze : std::unique_ptr
, std::shared_ptr
undstd::weak_ptr
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 überlastet *
. Das bedeutet, dass Ihr Objekt semantisch wie ein Zeiger aussieht, Sie es jedoch viel cooler machen können, einschließlich Referenzzählung, automatischer Zerstörung usw.,
shared_ptr
und auto_ptr
in den meisten Fällen ausreichend sind, aber mit ihren eigenen kleinen Eigenheiten einhergehen.
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, aber 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 zugewiesen werden müssen, 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, sodass beim Löschen des Objekts auch alle eigenen 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). .
Möglicherweise möchten Sie keinen intelligenten Zeiger verwenden, wenn:
Siehe auch:
Die meisten Arten von intelligenten Zeigern übernehmen die Entsorgung des Zeigerobjekts für Sie. Dies ist sehr praktisch, da Sie nicht mehr daran denken müssen, Objekte manuell zu entsorgen.
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 befasst sich mit einer Vielzahl von Entsorgungsszenarien, einschließlich Fällen, in denen Objekte "über DLL-Grenzen hinweg übergeben werden müssen" (der übliche Albtraumfall, falls abweichend) libc
zwischen Ihrem Code und den DLLs s verwendet werden).
Ein intelligenter Zeiger ist ein Objekt, das sich wie ein Zeiger verhält, aber zusätzlich die 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.
Zum Beispiel - Boost bietet die folgenden Smart - Pointer - Implementierungen:
shared_ptr<T>
ist ein Zeiger auf die T
Verwendung eines Referenzzählers, 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ählzeiger. Es bietet eine bessere Leistung als shared_ptr
, erfordert jedoch, dass der Typ T
einen eigenen Referenzzählmechanismus bereitstellt.weak_ptr<T>
ist ein schwacher Zeiger, der zusammen mit Zirkelverweisen arbeitet shared_ptr
.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, die je nach Bedarf verwendet werden kann. Weitere Einzelheiten und Beispiele finden Sie in der Dokumentation von Boost.
Darüber hinaus bietet die C ++ - Standardbibliothek drei intelligente Zeiger. std::unique_ptr
für einzigartiges Eigentum, std::shared_ptr
für gemeinsames Eigentum und std::weak_ptr
. std::auto_ptr
existierte in C ++ 03, ist aber jetzt veraltet.
scoped_ptr
es sich nicht um eine lokal deklarierte const unique_ptr
Datei handelt, die auch beim Verlassen des Bereichs gelöscht wird.
Hier ist der Link für ähnliche Antworten: http://sickprogrammersarea.blogspot.in/2014/03/technical-interview-questions-on-c_6.html
Ein intelligenter Zeiger 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 kapseln 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 überprü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 besteht darin, dass sie im Gegensatz zu regulären Zeigern die Vererbung nicht berücksichtigen. Intelligente Zeiger sind für polymorphen Code unattraktiv. Im Folgenden finden Sie ein Beispiel für die Implementierung intelligenter Zeiger.
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);
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 Überprüfung von Grenzen 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 Zweck der Speicherverwaltung auf sie zeigen. Der Missbrauch von Zeigern ist eine Hauptursache für Fehler: Die ständige Zuweisung, Freigabe und Referenzierung, die von einem mit Zeigern geschriebenen Programm durchgeführt werden muss, macht es sehr wahrscheinlich, dass Speicherlecks auftreten. Intelligente Zeiger versuchen, Speicherlecks zu verhindern, indem sie die Freigabe von Ressourcen automatisch vornehmen: Wenn der Zeiger auf ein Objekt (oder der letzte in einer Reihe von Zeigern) zerstört wird,
In diesem Tutorial sei T eine Klasse. Zeiger in C ++ können in drei Typen unterteilt werden:
1) Rohzeiger :
T a;
T * _ptr = &a;
Sie halten eine Speicheradresse an einer Stelle im Speicher. Seien Sie vorsichtig, da Programme komplex werden und schwer zu verfolgen sind.
Zeiger mit konstanten Daten oder Adresse {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 konstanter 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 als Zeiger ändern. dh. ptr3-- ; ptr3++ ; *ptr3 = 19;
wird nicht funktionieren
3) Intelligente Zeiger : { #include <memory>
}
Geteilter Zeiger :
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 mithilfe der Referenzzählung, um zu verfolgen, wie viele "Dinge" auf das Objekt zeigen, auf das der Zeiger zeigt. Wenn diese Anzahl auf 0 geht, wird das Objekt automatisch gelöscht, dh das Objekt wird gelöscht, wenn alle auf das Objekt zeigenden share_ptr den Gültigkeitsbereich verlassen. Dadurch entfällt der Kopfschmerz, Objekte löschen zu müssen, die Sie mit new zugewiesen haben.
Schwacher Zeiger: Hilft beim Umgang mit zyklischen Referenzen, die bei Verwendung des gemeinsamen Zeigers auftreten. Wenn Sie zwei Objekte haben, auf die zwei gemeinsame Zeiger zeigen, und ein interner gemeinsamer Zeiger auf den gemeinsamen Zeiger des anderen zeigt, gibt es eine zyklische Referenz und das Objekt nicht gelöscht werden, wenn freigegebene Zeiger den Gültigkeitsbereich verlassen. Um dies zu lösen, ändern Sie das interne Mitglied von shared_ptr in schwach_ptr. Hinweis: Um mit lock () auf das Element zuzugreifen, auf das ein schwacher Zeiger zeigt, wird ein schwaches_ptr zurückgegeben.
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 :: schwach_ptr nützlich?
Einzigartiger Zeiger: Leichter intelligenter Zeiger mit exklusivem Besitz. Verwenden Sie diese Option, 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 betrachtet werden, dh als Zeiger, der const ist und nicht mit besserer 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
Referenz: https://www.youtube.com/channel/UCEOGtxYTB6vo6MQ-WQ9W_nQ Vielen Dank an Andre für den Hinweis auf diese Frage.
Ein intelligenter Zeiger ist eine Klasse, ein Wrapper eines normalen Zeigers. Im Gegensatz zu normalen Zeigern basiert der Lebenskreis des Smart Points auf einem Referenzzähler (wie oft das Smart Pointer-Objekt zugewiesen wurde). Wenn also ein intelligenter Zeiger einem anderen zugewiesen wird, zählt die interne Referenz plus plus. Und wenn das Objekt den Gültigkeitsbereich verlässt, zählt die Referenz minus minus.
Der automatische Zeiger sieht zwar ähnlich aus, unterscheidet sich jedoch grundlegend vom intelligenten Zeiger. Es ist eine praktische Klasse, die die Zuordnung der Ressource aufhebt, wenn ein automatisches Zeigerobjekt den variablen Bereich verlässt. Bis zu einem gewissen Grad funktioniert ein Zeiger (auf dynamisch zugewiesenen Speicher) ähnlich wie eine Stapelvariable (statisch in der Kompilierungszeit zugewiesen).
Intelligente Zeiger sind solche, bei denen Sie sich nicht um die Aufhebung der Speicherzuweisung, die gemeinsame Nutzung von Ressourcen und die Übertragung kümmern müssen.
Sie können diesen Zeiger sehr gut verwenden, ähnlich wie jede Zuordnung in Java funktioniert. In Java macht Garbage Collector den Trick, während in Smart Pointers der Trick von Destruktoren ausgeführt wird.
Die vorhandenen Antworten sind gut, decken jedoch nicht ab, was zu tun ist, wenn ein intelligenter Zeiger nicht die (vollständige) Antwort auf das Problem ist, das Sie lösen möchten.
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 gestellt werden muss, wenn Sie versucht sind, eine abstrakte (oder tatsächlich eine beliebige) Basisklasse als Rückgabetyp in C ++ anzugeben, lautet "Was meinen Sie wirklich?". Es gibt eine gute Diskussion (mit weiteren Referenzen) über die idiomatische objektorientierte Programmierung in C ++ (und wie sich diese von anderen Sprachen unterscheidet) in der Dokumentation des Boost-Pointer-Container-Bibliothek. Zusammenfassend muss man in C ++ über das Eigentum nachdenken. Welche intelligenten Zeiger helfen Ihnen, sind aber nicht die einzige Lösung oder immer eine vollständige Lösung (sie geben Ihnen keine polymorphe Kopie) und sind nicht immer eine Lösung, die Sie in Ihrer Benutzeroberfläche verfügbar machen 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 (Smart Pointer, Zeigercontainer oder einfache Rückgabe einer Referenz) haben Sie die Rückgabe von einem Wert in eine Form von geändert oder Referenz. Wenn Sie wirklich eine Kopie benötigen, müssen Sie möglicherweise mehr Boilerplate "idiom" hinzufügen oder über idiomatisches (oder anderweitiges) OOP in C ++ hinausgehen, um mithilfe von Bibliotheken wie Adobe Poly einen allgemeineren Polymorphismus zu erzielen Boost.TypeErasure erzielen .