Was ist Copy Elision und wie optimiert es das Copy-and-Swap-Idiom?

Lesezeit: 3 Minuten

Was ist Copy Elision und wie optimiert es das Copy and Swap Idiom
Yogesh Arora

ich habe gelesen Kopieren und tauschen.

Ich habe versucht, einige Links zu Copy Elision zu lesen, konnte aber nicht richtig herausfinden, was es bedeutet. Kann bitte jemand erklären, was diese Optimierung ist, und insbesondere, was mit dem folgenden Text gemeint ist

Dies ist nicht nur eine Frage der Bequemlichkeit, sondern vielmehr eine Optimierung. Wenn der/die Parameter an einen lvalue (ein anderes nicht-konstantes Objekt) gebunden wird/werden, wird beim Erstellen des/der Parameter(s) automatisch eine Kopie des Objekts erstellt. Wenn s jedoch an einen rvalue (temporäres Objekt, Literal) bindet, wird die Kopie normalerweise eliminiert, was den Aufruf eines Kopierkonstruktors und eines Destruktors erspart. In der früheren Version des Zuweisungsoperators, in der der Parameter als konstanter Verweis akzeptiert wird, findet keine Kopierelision statt, wenn der Verweis an einen Rvalue gebunden wird. Dies führt dazu, dass ein zusätzliches Objekt erstellt und zerstört wird.

  • Verwandte: Was ist Copy Elision?

    – MM

    13. Januar 15 um 7:22 Uhr

1643700007 800 Was ist Copy Elision und wie optimiert es das Copy and Swap Idiom
R. Samuel Klatschko

Der Kopierkonstruktor existiert, um Kopien zu erstellen. Theoretisch, wenn Sie eine Zeile schreiben wie:

CLASS c(foo());

Der Compiler müsste den Kopierkonstruktor aufrufen, um die Rückgabe von zu kopieren foo() hinein c.

Copy Elision ist eine Technik, um den Aufruf des Copy-Konstruktors zu überspringen, um den Overhead nicht zu bezahlen.

Das kann zum Beispiel der Compiler arrangieren foo() wird direkt seinen Rückgabewert in konstruieren c.

Hier ist ein weiteres Beispiel. Nehmen wir an, Sie haben eine Funktion:

void doit(CLASS c);

Wenn Sie es mit einem tatsächlichen Argument aufrufen, muss der Compiler den Kopierkonstruktor aufrufen, damit der ursprüngliche Parameter nicht geändert werden kann:

CLASS c1;
doit(c1);

Betrachten Sie nun ein anderes Beispiel. Nehmen wir an, Sie rufen Ihre Funktion wie folgt auf:

doit(c1 + c1);

operator+ muss ein temporäres Objekt (einen Rvalue) erstellen. Anstatt den Kopierkonstruktor vor dem Aufruf aufzurufen doit()kann der Compiler das temporäre übergeben, das von erstellt wurde operator+ und das weitergeben doit() stattdessen.

Hier ist ein Beispiel:

#include <vector>
#include <climits>

class BigCounter {
 public:
   BigCounter &operator =(BigCounter b) {
      swap(b);
      return *this;
   }

   BigCounter next() const;

   void swap(BigCounter &b) {
      vals_.swap(b);
   }

 private:
   typedef ::std::vector<unsigned int> valvec_t;
   valvec_t vals_;
};

BigCounter BigCounter::next() const
{
   BigCounter newcounter(*this);
   unsigned int carry = 1;
   for (valvec_t::iterator i = newcounter.vals_.begin();
        carry > 0 && i != newcounter.vals_.end();
        ++i)
   {
      if (*i <= (UINT_MAX - carry)) {
         *i += carry;
      } else {
         *i += carry;
         carry = 1;
      }
   }
   if (carry > 0) {
      newcounter.vals_.push_back(carry);
   }
   return newcounter;
}

void someFunction()
{
    BigCounter loopcount;
    while (true) {
       loopcount = loopcount.next();
    }
}

In somefunction die Linie loopcount = loopcount.next(); profitiert stark von der Kopierelision. Wenn das Entfernen von Kopien nicht zulässig wäre, würde diese Zeile drei Aufrufe des Kopierkonstruktors und einen zugehörigen Aufruf eines Destruktors erfordern. Da das Entfernen von Kopien erlaubt ist, kann es auf 1 Aufruf des Kopierkonstruktors reduziert werden, den expliziten innerhalb von BigCount::next() wo newcounter ist deklariert.

Wenn operator = wurde so deklariert und definiert:

BigCounter &BigCounter::operator =(const BigCounter &b) {
   BigCounter tmp(b);
   swap(tmp);
   return *this;
}

Es hätte 2 Aufrufe des Kopierkonstruktors geben müssen, selbst wenn die Kopie entfernt wurde. Eine zum Konstruieren newcounter und die andere zum konstruieren tmp. Und ohne Copy Elision wären es immer noch 3. Deshalb deklarieren operator = Daher erfordert sein Argument, dass das Aufrufen des Kopierkonstrukts eine Optimierung sein kann, wenn das Idiom „Kopieren und Tauschen“ für den Zuweisungsoperator verwendet wird. Wenn der Kopierkonstruktor zum Erstellen eines Arguments aufgerufen wird, kann sein Aufruf weggelassen werden, aber wenn er aufgerufen wird, um eine lokale Variable zu erstellen, ist dies möglicherweise nicht der Fall.

.

724420cookie-checkWas ist Copy Elision und wie optimiert es das Copy-and-Swap-Idiom?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy