foo
полностью инициализируется после ввода тела конструктора (это гарантированный общий случай; особенно после завершения инициализации в списке инициализации.)
В вашем случае вы создаете копию из неструктурированного объекта. Это приводит к неопределенному поведению, согласно §12.7 / 1 (спасибо, gf):
Для объекта типа класса, отличного от POD (раздел 9), перед тем, как конструктор начнет выполнение и после того, как деструктор закончит выполнение, обращение к любому нестатическому члену или базовому классу объекта приведет к неопределенному поведению.
На самом деле, он дает такой пример:
struct W { int j; };
struct X : public virtual W { };
struct Y {
int *p;
X x;
Y() : p(&x.j) // undefined, x is not yet constructed
{ }
};
Обратите внимание, что компилятор не необходим для постановки диагноза неопределенного поведения, согласно §1.4 / 1. Хотя я думаю, что все мы согласны с тем, что это было бы неплохо, разработчикам компиляторов просто не о чем беспокоиться.
Чарльз указывает на какую-то лазейку. Если Bar
имеет статическое хранилище и если Foo
является типом POD, то будет инициализироваться при запуске этого кода. Статические переменные инициализируются нулями перед выполнением другой инициализации.
Это означает, что независимо от Foo
, поскольку для его инициализации не требуется конструктор (т. Е. POD), его члены будут инициализироваться нулями. По сути, вы будете копировать инициализированный нулем объект.
В общем, такого кода следует избегать. :)