#c #initialization #copy-elision #copy-initialization
#c #инициализация #копирование-устранение #копирование-инициализация
Вопрос:
В следующих двух сегментах кода представлена задача инициализации переменной b
как копии a
. Первый сегмент кода инициализирует переменную с помощью инициализации копирования (инициализация с использованием =
). Предположим, что класс Apple
просто определен как пустой класс: class Apple {};
Apple a;
Apple b = a;
Второй сегмент кода инициализирует переменную, также используя инициализацию копирования. Хотя то, что копируется при инициализации, является копией a
.
Apple a;
Apple b = Apple(a);
При чтении этого вслепую кажется, что копирование происходит at Apple(a)
, а другое at Apple b = ...
. В противоречии, переопределение конструктора копирования Apple
для печати чего-либо в копии показывает, что во время выполняется только одна копия Apple b = Apple(a)
.
Являются ли эти два оператора Apple b = a;
и Apple b = Apple(a);
идентичными? Существуют ли случаи, когда они не идентичны?
Ответ №1:
Да, по идее Apple b = Apple(a);
, сначала создается временное Apple
a
, а затем b
инициализируется копирование из временного. Из-за исключения копирования, поскольку эффект b
инициализируется a
напрямую.
При следующих обстоятельствах компиляторы должны опустить копирование и переместить построение объектов класса, даже если конструктор копирования / перемещения и деструктор имеют наблюдаемые побочные эффекты. Объекты создаются непосредственно в хранилище, куда они в противном случае были бы скопированы / перемещены. Конструкторы копирования / перемещения не обязательно должны присутствовать или быть доступными:
- При инициализации объекта, когда выражение инициализатора является значением prvalue того же типа класса (игнорируя cv-квалификацию), что и тип переменной:
Этот вид исключения копирования гарантирован начиная с C 17, до C 17 это оптимизация. При компиляции в режиме до C 17 и с опцией, запрещающей оптимизацию, вы можете увидеть разницу между двумя случаями.
Комментарии:
1. Была ли эта оптимизация до C 17 реализована независимо разработчиками компилятора? Или, была ли официальная документация, в которой говорилось, что разработчики компилятора должны рассмотреть возможность реализации этой оптимизации?
2. @TarasPalczynski Стандарт не требует такой оптимизации до C 17, он просто допускает такую оптимизацию. Хотя большинство компиляторов, которые я знаю, поддерживают это.
3. Есть ли какой-либо ресурс, который указывает в списке, какие компиляторы поддерживают эту оптимизацию до C 17? Или единственный реалистичный способ — просто попробовать каждый компилятор и посмотреть, что он делает?
4. @TarasPalczynski Боюсь, я этого не знаю… Возможно, вам потребуется проверить документ компиляторов или протестировать код.