Frage

Wenn ich eine Funktion habe, die mit a funktionieren muss shared_ptr, wäre es nicht effizienter, ihm einen Verweis darauf zu übergeben (um das Kopieren zu vermeiden). shared_ptr Objekt)?Was sind die möglichen schlimmen Nebenwirkungen?Ich stelle mir zwei mögliche Fälle vor:

1) Innerhalb der Funktion wird eine Kopie des Arguments erstellt, wie in

ClassA::take_copy_of_sp(boost::shared_ptr<foo> &sp)  
{  
     ...  
     m_sp_member=sp; //This will copy the object, incrementing refcount  
     ...  
}  

2) Innerhalb der Funktion wird das Argument nur verwendet, wie in

Class::only_work_with_sp(boost::shared_ptr<foo> &sp) //Again, no copy here  
{    
    ...  
    sp->do_something();  
    ...  
}  

Ich kann in beiden Fällen keinen guten Grund erkennen, den zu bestehen boost::shared_ptr<foo> nach Wert statt nach Referenz.Die Übergabe eines Werts würde den Referenzzähler aufgrund des Kopierens nur „vorübergehend“ erhöhen und ihn dann beim Verlassen des Funktionsbereichs dekrementieren.Übersehe ich etwas?

Nur zur Klarstellung, nachdem ich mehrere Antworten gelesen habe:Ich stimme den Bedenken hinsichtlich der vorzeitigen Optimierung vollkommen zu und versuche immer, zuerst ein Profil zu erstellen und dann an den Hotspots zu arbeiten.Meine Frage war eher aus rein technischer Code-Sicht, wenn Sie wissen, was ich meine.

War es hilfreich?

Lösung

Der Punkt einer gesonderten shared_ptr Instanz (soweit möglich) zu gewährleisten, dass, solange diese shared_ptr im Gültigkeitsbereich befindet, wird das Objekt verweist er auf noch existieren, weil der Referenzzähler mindestens 1 sein wird.

Class::only_work_with_sp(boost::shared_ptr<foo> sp)
{
    // sp points to an object that cannot be destroyed during this function
}

So durch einen Verweis auf eine shared_ptr verwenden, deaktivieren Sie diese Garantie. Also in Ihrem zweiten Fall:

Class::only_work_with_sp(boost::shared_ptr<foo> &sp) //Again, no copy here  
{    
    ...  
    sp->do_something();  
    ...  
}

Wie wissen Sie, dass sp->do_something() nicht sprengen aufgrund einer Null-Zeiger?

Es hängt alles, was in diesen ist ‚...‘ Abschnitte des Codes. Was ist, wenn Sie etwas beim ersten Anruf ‚...‘, die den Nebeneffekt hat (irgendwo in einem anderen Teil des Codes) zur Herstellung eines shared_ptr zu demselben Objekt Clearing? Und was ist, wenn es der einzige verbleibende deutliche shared_ptr auf das Objekt passiert sein? Bye bye Objekt, gerade da, wo Sie sind dabei, zu versuchen, und verwenden Sie es.

Es gibt also zwei Möglichkeiten, diese Frage zu beantworten:

  1. , um die Quelle des gesamten Programms mit sehr sorgfältig, bis Sie das Objekt sicher sind, nicht während der Funktion Körpers sterben.

  2. den Parameter ändern zurück anstelle eines Verweises ein separates Objekt zu sein.

Allgemeine Bit der Beratung, die hier gilt: nicht die Mühe, riskante Änderungen an Ihren Code aus Gründen der Leistung machen, bis Sie Ihr Produkt in einer realistischen Situation in einem Profiler und schlüssig gemessen, dass die Änderung, die Sie machen wollen timed haben zu macht einen signifikanten Unterschied zur Performance wird.

Update für commenter JQ

Hier ist ein konstruiertes Beispiel. Es ist bewusst einfach, so wird der Fehler offensichtlich. In realen Beispielen ist der Fehler nicht so offensichtlich, weil sie in Schichten von realem Detail verborgen ist.

Wir haben eine Funktion, die eine Nachricht irgendwo senden. Es kann eine große Nachricht sein, so anstatt ein std::string verwenden, die wahrscheinlich kopiert wird, wie es um an mehreren Stellen übergeben wird, verwenden wir eine shared_ptr in einen String:

void send_message(std::shared_ptr<std::string> msg)
{
    std::cout << (*msg.get()) << std::endl;
}

(Wir haben gerade „Senden“ an die Konsole für dieses Beispiel).

Jetzt wollen wir eine Anlage hinzufügen, um die vorherige Nachricht zu erinnern. Wir wollen das folgende Verhalten: eine Variable muss vorhanden sein, dass die zuletzt gesendete Nachricht enthält, aber während einer Nachricht zur Zeit dann muss es gesendet wird keine vorherige Nachricht sein (die Variable sollte vor dem Senden zurückgesetzt werden). So erklären wir die neue Variable:

std::shared_ptr<std::string> previous_message;

Dann ändern wir unsere Funktion nach den Regeln, die wir angegeben:

void send_message(std::shared_ptr<std::string> msg)
{
    previous_message = 0;
    std::cout << *msg << std::endl;
    previous_message = msg;
}

Also, bevor wir zu senden beginnen verwerfen wir die aktuelle vorherige Nachricht, und dann nach dem Senden abgeschlossen wir die neue vorherige Nachricht speichern können. Alles gut. Hier einige Testcode:

send_message(std::shared_ptr<std::string>(new std::string("Hi")));
send_message(previous_message);

Und wie erwartet, diese Drucke Hi! zweimal.

Jetzt kommt Herr Maintainer, der an dem Code steht und sagt: Hey, das Parameter send_message ist ein shared_ptr:

void send_message(std::shared_ptr<std::string> msg)

Natürlich kann das geändert werden:

void send_message(const std::shared_ptr<std::string> &msg)

Denken Sie an die Leistungssteigerung dies bringen wird! (Es macht nichts, dass wir über eine normalerweise große Nachricht über einen gewissen Kanal zu senden, so wird die Leistungssteigerung so klein sein, wie unmeasureable zu sein).

Aber das eigentliche Problem ist, dass jetzt der Testcode nicht definiertes Verhalten zeigen wird (in Visual C ++ 2010 Debug bauen, stürzt).

Herr Maintainer wird davon überrascht, aber fügt eine defensive Prüfung in einem Versuch, send_message das Problem zu stoppen passiert:

void send_message(const std::shared_ptr<std::string> &msg)
{
    if (msg == 0)
        return;

Aber natürlich geht es noch weiter und stürzt ab, weil msg nie null ist, wenn send_message genannt wird.

Wie gesagt, mit all dem Code so nahe beieinander in einem trivialen Beispiel, ist es einfach, die Fehler zu finden. Aber im wirklichen Programm, mit komplexeren Beziehungen zwischen veränderbaren Objekten, die Zeiger zueinander halten, ist es leicht zu machen der Fehler, und schwer, die n zu konstruierenecessary Testfälle die Fehler zu erkennen.

Die einfache Lösung, in der Sie eine Funktion wollen verlassen kann auf einem shared_ptr gesamten seine Nicht-Null-Fortsetzung ist für die Funktion ihres eigenen wahren shared_ptr zuzuordnen, anstatt zu einem bestehenden shared_ptr auf eine Referenz angewiesen zu sein.

Der Nachteil ist, dass ein shared_ptr kopiert ist nicht frei: auch „Lock-frei“ Implementierungen hat eine Verriegelungsfunktion verwenden Threading Garantien zu ehren. So kann es Situationen geben, in denen ein Programm wesentlich durch Ändern eines shared_ptr in eine shared_ptr & beschleunigt werden. Aber es ist dies nicht eine Änderung, die sicher für alle Programme gemacht werden kann. Es ändert die logische Bedeutung des Programms.

Beachten Sie, dass ein ähnlicher Fehler auftreten würde, wenn wir std::string durchgehend verwendet statt std::shared_ptr<std::string>, und statt:

previous_message = 0;

die Meldung zu löschen, wir sagten:

previous_message.clear();

Dann wäre das Symptom der versehentlichen einer leeren Nachricht senden, statt nicht definiertes Verhalten. Die Kosten für eine zusätzliche Kopie eines sehr großen String können viel mehr von Bedeutung sein als die Kosten für ein shared_ptr Kopieren, so dass der Trade-off kann unterschiedlich sein.

Andere Tipps

fand ich mich mit der höchsten gestimmten Antwort nicht einverstanden, so ging ich für Experten opinons suchen und hier sind sie. Aus http://channel9.msdn.com/Shows/Going+Deep/C-and-Beyond-2011-Scott-Andrei-and-Herb-Ask-Us-Anything

Herb Sutter: "Wenn Sie Shared_ptr Pass, Kopien sind teuer"

Scott Meyers: „Es gibt nichts Besonderes Shared_ptr wenn es darum geht, ob Sie es nach Wert übergeben, oder es als Verweis übergeben Verwenden Sie genau die gleiche Analyse, die Sie für einen anderen benutzerdefinierten Typ verwenden Menschen scheinen diese Wahrnehmung zu haben, dass.. shared_ptr löst irgendwie alle Management-Probleme, und das, weil es klein ist, ist es unbedingt billig ist nach Wert zu übergeben. es hat kopiert werden, und es gibt eine Kosten damit verbunden ... es ist teuer es nach Wert zu übergeben, so dass, wenn ich kann, davonkommen mit dem richtigen Semantik in meinem Programm, ich werde Pass es durch Verweis oder Verweis auf const statt "

Herb Sutter: „passieren sie immer unter Bezugnahme auf const, und in sehr seltenen Fällen vielleicht, weil Sie wissen, was Sie das, was Sie von einem Verweis bekamen ändern nennen könnte, vielleicht dann könnten Sie nach Wert übergeben ..., wenn Sie kopieren sie als Parameter, oh meine Güte Sie fast nie brauchen, dass die Referenzzähler zu stoßen, weil sie ohnehin am leben gehalten hat ist, und Sie sollten es durch Bezugnahme vorbei, also bitte, dass "

Update: Herb hat auf diesem hier erweitert: http://herbsutter.com/2013/06/05/gotw-91-solution-smart-pointer-parameters/ , obwohl die Moral der Geschichte ist, dass man überhaupt nicht shared_ptr des passing „es sei denn, sollte Sie wollen die intelligenten Zeiger selbst, wie zu teilen oder zu Eigentum zu übertragen verwenden oder zu manipulieren. "

ich gegen diese Praxis raten würde, wenn Sie und die anderen Programmierer Sie mit wirklich funktionieren, wirklich wissen, was Sie alles tun.

Als erstes haben Sie keine Ahnung, wie die Schnittstelle zu Ihrer Klasse entwickeln könnte, und Sie wollen andere Programmierer verhindern, dass schlechte Dinge zu tun. ein shared_ptr Übergabe als Referenz ist kein Programmierer etwas sollte erwarten zu sehen, weil es nicht idiomatischen ist, und das macht es einfach falsch, es zu benutzen. Programm defensiv: macht die Schnittstelle schwer falsch zu verwenden. Übergabe als Referenz wird nur Probleme einladen später.

Zweitens, nicht optimieren, bis Sie diese besondere Klasse wissen, wird ein Problem sein. Profil zuerst, und dann, wenn Ihr Programm wirklich braucht, den Auftrieb gegeben durch durch Bezugnahme vorbei, dann vielleicht. Ansonsten nicht Kleinkram (das heißt die zusätzliche N Anweisungen, um es von Wert zu übergeben nimmt) statt Sorgen über Design, Datenstrukturen, Algorithmen und langfristige Wartbarkeit.

Ja, eine Referenz genommen ist es in Ordnung. Sie beabsichtigen nicht, die Methode Miteigentum zu geben; sie will nur mit ihm arbeiten. Sie könnten auch eine Referenz für den ersten Fall nehmen, da man es trotzdem kopieren. Aber für den ersten Fall ist es nimmt Eigentum. Es ist dieser Trick es noch kopiert nur einmal:

void ClassA::take_copy_of_sp(boost::shared_ptr<foo> sp) {
    m_sp_member.swap(sp);
}

Sie sollten auch kopieren, wenn Sie es zurück (das heißt nicht einen Verweis zurück). Da Ihre Klasse nicht weiß, was der Kunde mit ihm tut (es könnte einen Zeiger auf sie speichern und dann Urknall passiert). Wenn es später stellt sich heraus, es ist ein Engpass (erstes Profil!), Dann können Sie noch einen Verweis zurück.


Bearbeiten : Natürlich, wie andere darauf hin, dass dies nur wahr, wenn Sie Ihren Code kennen und wissen, dass Sie den übergebenen gemeinsamen Zeiger nicht in irgendeine Weise setzen. Im Zweifelsfall passiert nur durch Wert.

Es ist sinnvoll shared_ptrs von const& passieren. Es wird wahrscheinlich nicht Probleme verursachen (außer im unwahrscheinlichen Fall, dass die referenzierte shared_ptr während des Funktionsaufrufes gelöscht wird, wie durch Earwicker beschrieben), und es wird wahrscheinlich schneller sein, wenn Sie eine Menge von diesem herumreichen. Merken; der Standard-boost::shared_ptr ist Thread-sicher, so kopiert er enthält einen Thread sicher Schritt.

Versuchen const& zu verwenden, anstatt nur &, weil temporäre Objekte nicht durch nicht konstante Referenz übergeben werden können. (Auch wenn eine Spracherweiterung in MSVC ermöglicht es Ihnen, es trotzdem zu tun)

Im zweiten Fall, dies zu tun ist einfacher:

Class::only_work_with_sp(foo &sp)
{    
    ...  
    sp.do_something();  
    ...  
}

Sie können es als nennen

only_work_with_sp(*sp);

Ich würde eine „plain“ Referenz vermeiden, es sei denn die Funktion explizit den Zeiger ändern kann.

Ein const & kann eine sinnvolle Mikro-Optimierung sein, wenn kleine Funktionen aufrufen - z.B. weitere Optimierungen zu ermöglichen, wie einige Bedingungen inlining entfernt. Auch die Zunahme / Abnahme -, da es Thread-sicher ist - ist ein Synchronisationspunkt. Ich würde nicht erwarten, dass dies einen großen Unterschied in den meisten Szenarien zu machen, though.

Im Allgemeinen sollten Sie die einfachere Art verwenden, wenn Sie Grund haben, nicht zu tun. Dann entweder die const & konsequent, oder einen Kommentar hinzufügen, warum, wenn Sie es verwenden, nur an wenigen Stellen.

Ich würde befürworten, durch konstante Referenz geteilt Zeiger vorbei -. Eine Semantik, dass die Funktion mit dem Zeiger übergeben wird, um den Zeiger nicht besaß, das eine saubere Idiom für Entwickler ist

Die einzige Gefahr ist in mehreren Thread-Programmen werden die Aufgabe durch den gemeinsamen Zeiger gezeigt wird, wird in einem anderen Thread zerstört. So ist es sicher konstante Referenz gemeinsamen Zeigers zu sagen, mit sicher in Single-Threaded-Programm.

Passing Zeiger durch nicht konstante Referenz geteilt manchmal gefährlich ist -. Der Grund, die Swap ist und die Funktion Reset-Funktionen innerhalb kann aufrufen, um das Objekt zu zerstören, die nach wie vor gültig, nachdem die Funktion zurückkehrt gilt

Es geht nicht um eine vorzeitige Optimierung, ich denke, -. Es über die Vermeidung unnötiger Verschwendung von CPU-Zyklen ist, wenn Sie klar, was Sie tun möchten, ist und die Codierung Idiom fest von Ihrem anderen Entwicklern angenommen worden

Just my 2 cents: -)

Es scheint, dass alle Vor- und Nachteile hier tatsächlich auf jede Art von Referenz übergeben verallgemeinert werden nicht nur shared_ptr. Meiner Meinung nach, sollten Sie die Semantik vorbei Referenz, konstante Referenz und Wert kennen und sie richtig verwenden. Aber es gibt absolut nichts falsch mit shared_ptr durch Bezugnahme vorbei, es sei denn, Sie denken, dass alle Referenzen sind schlecht ...

Um zum Beispiel zurück:

Class::only_work_with_sp( foo &sp ) //Again, no copy here  
{    
    ...  
    sp.do_something();  
    ...  
}

Wie wissen Sie, dass sp.do_something() nicht sprengen aufgrund eines baumelnden Zeiger?

Die Wahrheit ist, dass, shared_ptr oder nicht, const oder nicht, das passieren könnte, wenn Sie einen Konstruktionsfehler haben, wie direkt oder indirekt das Eigentum an sp zwischen Threads teilen, missusing ein Objekt, das delete this tun, Sie haben ein kreisförmiges Eigentum oder anderes Eigentum Fehler.

Eine Sache, die ich noch nicht erwähnt zu sehen ist, dass, wenn Sie freigegebene Zeiger durch Verweis übergeben, können Sie die implizite Konvertierung verlieren, die Sie erhalten, wenn Sie eine abgeleitete Klasse geteilt Zeiger durch einen Verweis auf eine Basisklasse gemeinsamen Zeiger übergeben möchten .

Zum Beispiel dieser Code wird einen Fehler erzeugen, aber es wird funktionieren, wenn Sie test() ändern, so dass der freigegebene Zeiger nicht durch Verweis übergeben wird.

#include <boost/shared_ptr.hpp>

class Base { };
class Derived: public Base { };

// ONLY instances of Base can be passed by reference.  If you have a shared_ptr
// to a derived type, you have to cast it manually.  If you remove the reference
// and pass the shared_ptr by value, then the cast is implicit so you don't have
// to worry about it.
void test(boost::shared_ptr<Base>& b)
{
    return;
}

int main(void)
{
    boost::shared_ptr<Derived> d(new Derived);
    test(d);

    // If you want the above call to work with references, you will have to manually cast
    // pointers like this, EVERY time you call the function.  Since you are creating a new
    // shared pointer, you lose the benefit of passing by reference.
    boost::shared_ptr<Base> b = boost::dynamic_pointer_cast<Base>(d);
    test(b);

    return 0;
}

Ich gehe davon aus, dass Sie vertraut sind mit vorzeitiger Optimierung und werden diese entweder für akademische Zwecke zu fragen, oder weil Sie haben einige bereits bestehenden Code isoliert, die unter-performing ist.

Passing durch Bezugnahme in Ordnung

Passing durch konstante Referenz ist besser, und in der Regel verwendet werden kann, da es nicht const-ness zwingt auf das Objekt gerichtet.

Sie sind nicht der Gefahr des Zeiger aufgrund Verwendung einer Referenz zu verlieren. Dieses Ersuchen ist Beweis dafür, dass Sie eine Kopie des Smart-Pointer früher in dem Stapel und nur ein Thread besitzt einen Call-Stack haben, so dass bereits bestehende Kopie ist nicht weg.

Referenzen zu verwenden ist oft effizienter aus den Gründen, die Sie erwähnen, , aber nicht garantiert . Denken Sie daran, dass ein Objekt Dereferenzierung zu Arbeit nehmen. Ihr ideales Referenz-Nutzungsszenario wäre, wenn Ihre Codierstil viele kleine Funktionen beinhaltet, wo der Zeiger würde von der Funktion übergeben bekommen funktionieren, bevor funktioniert verwendet wird.

Sie sollten immer vermeiden Speichern Ihr Smart-Pointer als Referenz. Ihr Class::take_copy_of_sp(&sp) Beispiel zeigt die korrekte Verwendung dafür.

Wir sind nicht besorgt mit const Korrektheit Unter der Annahme (oder mehr, meinen Sie den Funktionen zu ermöglichen, die Lage sein, das Eigentum an den Daten zu ändern oder zu teilen, übergeben wird), vorbei an einem boost :: shared_ptr von Wert ist sicherer als es vorbei durch Verweis als wir zulassen, dass der ursprüngliche boost :: shared_ptr, es zu kontrollieren eigene Lebenszeit ist. Betrachten Sie die Ergebnisse des folgenden Code ...

void FooTakesReference( boost::shared_ptr< int > & ptr )
{
    ptr.reset(); // We reset, and so does sharedA, memory is deleted.
}

void FooTakesValue( boost::shared_ptr< int > ptr )
{
    ptr.reset(); // Our temporary is reset, however sharedB hasn't.
}

void main()
{
    boost::shared_ptr< int > sharedA( new int( 13 ) );
    boost::shared_ptr< int > sharedB( new int( 14 ) );

    FooTakesReference( sharedA );

    FooTakesValue( sharedB );
}

Aus dem obigen Beispiel sehen wir, dass vorbei sharedA durch Verweis erlaubt FooTakesReference die ursprünglichen Zeiger zurückgesetzt, die Verwendungszählung auf 0 es ist reduziert, es zu zerstören Daten sind. FooTakesValue , kann aber den ursprünglichen Zeiger nicht zurückgesetzt, garantiert sharedB der Daten ist noch brauchbar. Wenn zwangsläufig ein anderer Entwickler zusammen kommt und versucht, huckepack auf sharedA der fragile Existenz, folgt Chaos. Die glückliche sharedB Entwickler, jedoch geht nach Hause früh wie alles in Ordnung in seiner Welt ist.

Der Code Sicherheit, in diesem Fall schafft weit schwerer wiegt als jede Verbesserung der Geschwindigkeit Kopieren. Zur gleichen Zeit, die boost :: shared_ptr sollte Code Sicherheit verbessern. Es wird viel einfacher sein, von einer Kopie auf eine Referenz zu gehen, wenn etwas, diese Art von Nischen Optimierung erfordert.

Sandy schrieb:„Es scheint, dass alle Vor- und Nachteile hier tatsächlich auf JEDEN als Referenz übergebenen Typ verallgemeinert werden können, nicht nur auf shared_ptr.“

Stimmt bis zu einem gewissen Grad, aber der Sinn der Verwendung von shared_ptr besteht darin, Bedenken hinsichtlich der Objektlebensdauer auszuräumen und den Compiler dies für Sie erledigen zu lassen.Wenn Sie einen gemeinsam genutzten Zeiger als Referenz übergeben und zulassen, dass Clients Ihres Objekts mit Referenzzählung nicht konstante Methoden aufrufen, die möglicherweise die Objektdaten freigeben, ist die Verwendung eines gemeinsam genutzten Zeigers nahezu sinnlos.

Ich habe in diesem vorherigen Satz „fast“ geschrieben, weil die Leistung ein Problem darstellen kann und in seltenen Fällen gerechtfertigt sein „könnte“, aber ich würde dieses Szenario auch selbst vermeiden und selbst nach allen möglichen anderen Optimierungslösungen suchen, z. B. ernsthaft nachsehen beim Hinzufügen einer weiteren Ebene der Indirektion, verzögerten Auswertung usw.

Code, der über die Zeit seines Autors hinaus existiert oder sogar über dessen Gedächtnis hinausgeht, der implizite Annahmen über das Verhalten, insbesondere das Verhalten über die Lebensdauer von Objekten, erfordert, erfordert eine klare, prägnante und lesbare Dokumentation, und dann werden ihn viele Clients sowieso nicht lesen!Einfachheit geht fast immer vor Effizienz, und es gibt fast immer andere Möglichkeiten, effizient zu sein.Wenn Sie Werte wirklich als Referenz übergeben müssen, um ein tiefes Kopieren Ihrer Objekte mit Referenzzählung (und des Gleichheitsoperators) durch Kopierkonstruktoren zu vermeiden, sollten Sie vielleicht Möglichkeiten in Betracht ziehen, die tief kopierten Daten zu Zeigern mit Referenzzählung zu machen, die sein können schnell kopiert.(Das ist natürlich nur ein Entwurfsszenario, das möglicherweise nicht auf Ihre Situation zutrifft.)

habe ich in einem Projekt zu arbeiten, das das Prinzip sehr stark war, zu dem Übergeben intelligente Zeiger nach Wert. Als ich gefragt wurde, einig Performance-Analyse zu tun - ich fand, dass für Zuwachs und Abnahme der Referenzzähler des intelligenten Zeigers der Anwendung zwischen 4-6% der verwendeten Prozessorzeit verbringt

.

Wenn Sie die intelligenten Zeiger nach Wert übergeben wollen zu vermeiden, nur um mit Problemen in seltsamen Fällen von Daniel Earwicker beschrieben sicherstellen, dass Sie den Preis verstehen Sie dafür zu bezahlen.

Wenn Sie sich entscheiden, den Hauptgrund, mit einem Verweise auf gehen konstante Referenz zu verwenden, ist es möglich zu machen implizites Upcasting zu haben, wenn Sie freigegebene Zeiger übergeben müssen von Klasse Objekt, das die Klasse erbt Sie in der Schnittstelle verwendet werden.

Zusätzlich zu dem, was litb sagte, ich möchte darauf hinweisen, dass es wahrscheinlich durch konstante Referenz im zweiten Beispiel passieren, dass die Art und Weise Sie sicher, dass Sie nicht versehentlich geändert werden.

struct A {
  shared_ptr<Message> msg;
  shared_ptr<Message> * ptr_msg;
}
  1. Pass von Wert:

    void set(shared_ptr<Message> msg) {
      this->msg = msg; /// create a new shared_ptr, reference count will be added;
    } /// out of method, new created shared_ptr will be deleted, of course, reference count also be reduced;
    
  2. Pass von Referenz:

    void set(shared_ptr<Message>& msg) {
     this->msg = msg; /// reference count will be added, because reference is just an alias.
     }
    
  3. Pass von Zeiger:

    void set(shared_ptr<Message>* msg) {
      this->ptr_msg = msg; /// reference count will not be added;
    }
    

Jeder Code Stück muss einen Sinn tragen. Wenn Sie einen freigegebenen Zeiger nach Wert übergeben überall in der Anwendung bedeutet dies, „Ich bin nicht sicher, was anderswo passiert, daher bevorzugen wir rohe Sicherheit “. Das ist nicht das, was ich ein gutes Vertrauen Zeichen für andere Programmierer nennen, die den Code konsultieren könnten.

Wie auch immer, auch wenn eine Funktion eine konstante Referenz bekommt und Sie sind „nicht sicher“, können Sie immer noch eine Kopie des gemeinsamen Zeigers an der Spitze der Funktion erstellen, einen starken Bezug auf den Zeiger hinzuzufügen. Dies könnte auch als ein Hinweis über das Design zu sehen ist ( „der Zeiger geändert anderswo werden kann“).

Also ja, IMO, sollte der Standard sein " durch const Verweis übergeben ".

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top