Ответ 1
Комментарии предполагают, что MSVC 2008 использует временное, которое g++ не делает, чтобы передать параметр. Если это так, это ошибка. Из С++ 03 [dcl.init]/12:
Инициализация, возникающая при передаче аргумента, возврату функции, исключении исключения (15.1), обработке исключения (15.3) и списках инициализаторов, заключенных в фигурные скобки (8.5.1), называется копией-инициализацией и эквивалентна форме
T x = a;
Теперь вот критический бит. В T x = a;
, если a
не является T
или не получен из T
, то это эквивалентно T x = T(a);
, а концептуально используется дополнительное временное. (Это временное право на копирование).
Однако, если a
является T
или получен из T
, тогда не должно быть дополнительного временного. Это то же самое, что T x(a);
.
В этом вопросительном коде, поскольку B
происходит от a
, не должно быть временного.
Поддерживающий текст в С++ 03 находится под [dcl.init]/14 (я выделил части, относящиеся к этому образцу кода вопроса):
Если тип назначения является классом класса (возможно, cv-qualit):
- Если класс является агрегатом (8.5.1), а инициализатор представляет собой список, заключенный в скобки, см. 8.5.1.
- Если инициализация является прямой инициализацией или если она является копией-инициализацией, где cv-неквалифицированная версия типа источника является тем же классом, что и или производным классом, класс назначения, конструкторы. Соответствующие конструкторы перечислены (13.3.1.3), а лучший выбирается с помощью разрешения перегрузки (13.3). Выбранный таким образом конструктор вызывается для инициализации объекта с выражением инициализатора (s) в качестве его аргумента (ов). Если конструктор не применяется или разрешение перегрузки неоднозначно, инициализация плохо сформирована.
- В противном случае (т.е. для остальных случаев инициализации копии) пользовательские последовательности преобразований, которые могут конвертировать из типа источника в тип назначения или (когда используется функция преобразования) с их производный класс перечислены, как описано в 13.3.1.4, и лучший из них выбирается посредством разрешения перегрузки (13.3). Если преобразование не может быть выполнено или неоднозначно, инициализация плохо сформирована. Выбранная функция вызывается с выражением инициализатора в качестве аргумента; если функция является конструктором, , вызов инициализирует временный для целевого типа. Результат вызова (который является временным для случая конструктора) затем используется для прямого инициализации, согласно вышеприведенным правилам, объекта, который является местом назначения инициализации копирования. В некоторых случаях допускается исключить копирование, присущее этой прямой инициализации, путем создания промежуточного результата непосредственно в инициализированном объекте; см. 12.2, 12.8.