Что такое копирование и как он оптимизирует идиому копирования и свопинга?

Я читал « Копировать и своп» .

Я пробовал читать некоторые ссылки на Copy Elision, но не мог понять, что это значит. Может кто-нибудь объяснить, что такое оптимизация, и особенно то, что означает следующий текст

Это не просто вопрос удобства, а фактически оптимизация. Если параметр (ы) связывается с lvalue (другим неконстантным объектом), копия объекта создается автоматически при создании параметра (ов). Однако, когда s привязывается к rvalue (временному объекту, литералу), обычно копируется копия, которая сохраняет вызов конструктора копирования и деструктора. В более ранней версии оператора присваивания, где параметр принимается как константная ссылка, копирование не происходит, когда ссылка привязывается к rvalue. Это приводит к созданию и уничтожению дополнительного объекта.

Конструктор копирования существует для создания копий. Теоретически, когда вы пишете строку вроде:

CLASS c(foo()); 

Компилятор должен был бы вызвать конструктор копирования, чтобы скопировать возврат foo() в c .

Копирование elision – это метод, позволяющий пропустить вызов конструктора копирования, чтобы не оплачивать накладные расходы.

Например, компилятор может организовать, что foo() будет напрямую строить свое возвращаемое значение в c .

Вот еще один пример. Допустим, у вас есть функция:

 void doit(CLASS c); 

Если вы вызываете его с фактическим аргументом, компилятор должен вызвать конструктор копирования, чтобы исходный параметр не мог быть изменен:

 CLASS c1; doit(c1); 

Но теперь рассмотрим другой пример, допустим, вы вызываете свою функцию следующим образом:

 doit(c1 + c1); 

operator+ должен создать временный объект (rvalue). Вместо вызова конструктора копирования перед вызовом doit() компилятор может передать временное, созданное operator+ и передать это вместо doit() .

Вот пример:

 #include  #include  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 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(); } } 

В somefunction функции строка loopcount = loopcount.next(); выгоды от копирования. Если исключение копирования не было разрешено, для этой строки потребуется 3 вызова конструктора копирования и связанный с ним вызов деструктора. Если разрешено копирование, его можно свести к 1 вызову конструктора копирования, явному внутри BigCount::next() где объявлен newcounter .

Если operator = был объявлен и определен следующим образом:

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

там должно было быть 2 вызова конструктора копирования, даже с копией elision. Один для построения newcounter и другой для построения tmp . И без копирования элит все равно будет 3. Вот почему объявление operator = поэтому его аргумент требует вызова конструкции копирования, может быть оптимизацией при использовании идиомы «copy and swap» для оператора присваивания. Когда конструктор копирования вызывается для построения аргумента, его вызов может быть отменен, но если он вызывается для создания локальной переменной, это может и не быть.

  • Когда оптимизация преждевременна?
  • Как я могу ускорить свою программу Perl?
  • Почему memcmp намного быстрее, чем проверка цикла?
  • Многопоточность имеет смысл для операций с привязкой к IO?
  • Преимущество перехода на оператор if-else
  • для оптимизации цикла
  • Получение всех типов, реализующих интерфейс
  • Является ли компилятор C # достаточно умным, чтобы оптимизировать этот код?
  • Каков самый быстрый / самый эффективный способ найти самый старший бит набора (msb) в целых числах в C?
  • Действительно ли опечатанные classы действительно предлагают преимущества?
  • Когда компиляторы встроены в код C ++?
  • Interesting Posts

    Несовместимые плагины для android-apt после обновления до Android Studio 2.3

    Как скрыть строку состояния в Android

    Force InnoDB перепроверять foreign keys на столе / таблицах?

    двухсторонний график плотности в сочетании с односторонним графиком плотности с выбранными областями в r

    Почему моя голосовая команда отсутствует в меню ok в XE16?

    Образец торта с отменным абстрактным типом не работает с верхними границами

    В чем разница между скрытыми атрибутами HTML и ариями?

    Как контролировать объем мультимедиа?

    Как вставить строку между двумя строками в существующем excel с HSSF (Apache POI)

    Условная замена значений в data.frame

    Что такое ошибка времени выполнения SIGSEGV в C ++?

    LinkedList, помещенный в Intent extra, перерабатывается в ArrayList при получении в следующем действии

    Советы по проблеме java.lang.String.replace?

    Распечатайте файл ASCII на принтере, подключенном через USB

    Назад / Перемотка вперед в Word 2003/2007

    Давайте будем гением компьютера.