6 Stimmen

Übergabe als Wert oder Referenz an einen C++-Konstruktor, der eine Kopie speichern muss?

Sollte ein (impliziter oder expliziter) C++-Wert-Konstruktor seine(n) Parameter als Wert oder als Verweis auf eine Konstante akzeptieren, wenn er eine Kopie des/der Argumente(s) in seinem Objekt speichern muss, egal wie?

Hier ist das kürzeste Beispiel, das mir einfällt:

struct foo {
    bar _b;
    foo(bar [const&] b) // pass by value or reference-to-const?
        : _b(b) { }
};

Die Idee dabei ist, dass ich die Aufrufe des Kopierkonstruktors von bar minimieren möchte, wenn ein foo-Objekt erstellt wird, und zwar auf jede der verschiedenen Arten, auf die ein foo-Objekt erstellt werden könnte.

Bitte beachten Sie, dass ich ein wenig über Copy Elision und (Named) Return Value Optimization weiß, und ich habe gelesen "Schnelligkeit gewünscht? Pass by Value" Ich glaube jedoch nicht, dass der Artikel direkt auf diesen Anwendungsfall eingeht.

Bearbeiten: Ich sollte genauer sein.

Gehen Sie davon aus, dass ich nicht wissen kann, welche sizeof(bar) oder ob bar ist ein grundlegender, eingebauter Typ ( bar kann ein Vorlagenparameter sein, und foo kann eine Klassenvorlage statt einer Klasse sein). Gehen Sie auch nicht davon aus, dass foo Konstruktor kann inlined werden (oder bar und die der anderen). Gehen Sie davon aus, dass ich zumindest einen Compiler verwenden könnte, der RVO implementiert.

Was ich möchte, ist, dass es eine Möglichkeit gibt (angesichts der Compiler-Optimierungen), dass ein Aufruf wie dieser keine Aufrufe an bar Kopierkonstruktor (auch bei der Ausführung von _b(b) en foo der Initialisierungsliste):

foo f = function_that_creates_and_returns_a_bar_object_using_rvo();

Gibt es irgendeine Möglichkeit (angesichts des C++98-Standards), dass dies möglich ist, und wenn ja, ist es mehr oder weniger wahrscheinlich, dass es funktioniert, wenn foo seinen Parameter per Referenz-zu-Konst statt per Wert akzeptiert?

1voto

Thanatos Punkte 40150

Ich nehme an, dass bar hat einen normalen Kopierkonstruktor der Form bar(const bar &b)

Nehmen Sie hier einen Vergleichswert. bar Der Konstruktor des Programms nimmt dann diese Referenz und führt die Kopie aus. Kopien insgesamt: 1.

Wenn Sie den Verweis weglassen würden, würde der Compiler eine Kopie von b erstellen und diese Kopie an foo Konstruktor, der es dann an bar und kopieren Sie das.

0voto

rlbond Punkte 62333

Ehrlich gesagt, ist es in diesem Fall am besten, den Konstruktor inline vorausgesetzt bar Konstruktor nicht auslöst. Dann einfach per Referenz übergeben.

Wie Sie bereits vermutet haben, trifft Ihr Artikel hier nicht zu.

-1voto

Patrick Punkte 7763

Halten Sie einen shared_pointer auf bar in Ihrer Klasse und übergeben Sie ihn als solchen. Auf diese Weise rufen Sie niemals den Kopierkonstruktor auf :).

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X