Итак, вы используете 'copy-initialization':
8.5 / 11 Initializers
Форма инициализации (с использованием скобок или =), как правило, незначительна, ноимеет значение, когда инициализируемая сущность имеет тип класса;увидеть ниже....
Инициализация, которая происходит при передаче аргумента, возврате функции, генерации исключения (15.1), обработке исключения (15.3) и заключенных в скобки списках инициализаторов (8.5.1), называется copy-initializationи эквивалентно форме
T x = a;
Инициализация, которая происходит в новых выражениях (5.3.4), выражениях static_cast (5.2.9), преобразованиях типов функциональных обозначений (5.2.3), а также в основе и членеИнициализаторы (12.6.2) называются прямой инициализацией и эквивалентны форме
T x(a);
В 13.3.1.3 «Инициализация с помощью конструктора» перегрузки для выбранного конструктора:
Когда объекты типа класса инициализируются напрямую (8.5) или инициализируются копией из выражения того же или производного типа класса (8.5), разрешение перегрузки выбирает конструктор.Для прямой инициализации все функции-кандидаты являются конструкторами класса инициализируемого объекта.Для инициализации копирования все функции-кандидаты являются конструкторами преобразования (12.3.1) этого класса.
Таким образом, для инициализации копирования должен быть доступен конструктор копирования.Однако компилятору разрешено «оптимизировать» копию:
12.2 / 1 Временные объекты
Даже если создание временного объекта исключается (12.8), всесемантические ограничения должны соблюдаться, как если бы временный объект был создан.[Пример: даже если конструктор копирования не вызывается, все семантические ограничения, такие как доступность (пункт 11), должны быть выполнены.]
Вы можете получить желаемый эффект, избегая инициализации копирования и используя прямую инициализацию:
const A &b(B());
Примечание:
С более новымиверсии GCC, по-видимому, имеют другое поведение, я думал, что я опубликую эту заметку, которая может устранить разницу (при том, что оба поведения по-прежнему соответствуют стандартам):
8.5.3 / 5 Ссылки говорят:
Если выражение инициализатора является r-значением, с T2 типом класса, а «cv1 T1» совместимо со ссылками с «cv2 T2», ссылка связывается одним из следующих способов (выбор - реализацияопределены):
Ссылка привязана к объекту, представленному значением r (см. 3.10), или подобъекту в этом объекте.
Создается временный объект типа «cv1 T2» [sic], и вызывается конструктор для копирования всего объекта rvalue во временный объект.Ссылка привязана к временному или подобъекту во временном.
Конструктор, который будет использоваться для создания копии, должен вызываться независимо от того, выполняется ли копия на самом деле или нет..
Первоначально я прочитал последнее предложение («конструктор, который будет использоваться ...»), чтобы применить его к обоим вариантам, но, возможно, его следует читать как относящийся только к параметру секунд - илипо крайней мере, возможно, именно так читатели GCC читают это.
Я не уверен, что именно это происходит между различными версиями GCC (комментарии приветствуются).Мы определенно достигли предела моих языковых навыков юриста ...