Конструктор копирования / Оператор присваивания

Я узнал об автоматических преобразованиях в Accelerated C ++, и автор заявляет, что конструктор копирования всегда вызывается, когда у вас есть оператор в форме

myClass myVar = 24;

Кроме того, он утверждает, что когда у вас есть заявления в форме

myClass myVar;
myVar = 24;

на самом деле происходит то, что конструктор myClass, который принимает целое число в качестве аргумента, вызывается для создания неназванной временной переменной типа myClass, а затем вызывается оператор присваивания. Я считаю, что книга была написана в 2000 году. Мой вопрос заключается в том, верны ли эти утверждения до сих пор. Я узнал о конструкторе перемещения и операциях присваивания перемещения в другом месте, и мне было интересно, были ли они вызваны вместо оператора присваивания / конструктора копирования.

Спасибо за ваше время. Я очень ценю это.

0

Решение

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

myClass myVar = 24;

Неправильно.

Ваша книга была написана до того, как C ++ 11 стал новым стандартом, поэтому в ней не упоминается семантика перемещения и вероятность того, что шаг-конструктор можно назвать. Более того, речь не идет о копирования элизия. Да, это правда, что вызываемый конструктор копирования может быть вызван, но из-за оптимизации под названием copy-elison компилятору разрешено удалить вызов из конструктора копирования / перемещения. Это разрешено, даже если это может повлиять на поведение программы, но учтите, что это не гарантированный случиться на каждом компиляторе.

Если вы напишите программа чтобы проверить это поведение, вы обнаружите, что конструктор копирования / перемещения не вызывается. Передача аргумента командной строки -fno-elide-constructors отключает это разрешение и разрешает звонок от шаг-конструктор.

Форма инициализации, которую вы используете, называется копия инициализация:

§ 8.5 / 15 Инициализаторы

Инициализация, которая происходит в форме

T x = a;

а также в
передача аргумента, возврат функции, выдача исключения (15.1),
обработка исключения (15.3) и инициализация составного элемента
(8.5.1) называется копия инициализация. [ Заметка: Копия-инициализация может
вызвать ход (12.8)
. — конец примечания]

Предполагая, что copy-elision не имеет места, компилятор создаст временный экземпляр класса для преобразования в указанный тип. Затем он скопирует или переместит конструкцию myVar из этого временного с помощью конструктора копирования или Move-конструктор. Конструктор перемещения имеет приоритет над конструктором копирования для значений r и будет вызываться только в том случае, если у вашего класса есть доступный конструктор перемещения; в противном случае вызывается конструктор копирования.

Если copy-elision не происходит, компилятор инициализирует myVar как если бы он был сконструирован с правой стороны. Это в соответствии с как будто правило в котором говорится, что компилятор может выполнять оптимизацию, учитывая, что это не влияет на наблюдаемое поведение программы.

Кроме того, он утверждает, что когда у вас есть заявления в форме

myClass myVar;
myVar = 24;

на самом деле происходит то, что myClass
конструктор, который принимает целое число в качестве аргумента, вызывается для создания
безымянная временная переменная типа myClassа затем
оператор присваивания называется. […] Мой вопрос заключается в том, верны ли эти заявления.

Да, конструкторы принимают участие в неявных преобразованиях типов. Из последнего проекта, N3797:

§ 12.3 Преобразования

Преобразования типов объектов класса могут быть определены конструкторы а также
по функциям преобразования. Эти преобразования называются определяемые пользователем
преобразования
и используются для неявных преобразований типов (раздел 4), для
инициализация (8.5) и для явных преобразований типов (5.4, 5.2.9)

Объяснение, данное вашим автором в этой части, было правильным, за исключением того факта, что оператор присваивания будет вызван, если это доступно.

2

Другие решения