Они не полностью идентичны. Первый называется «прямой инициализацией», а второй - «инициализацией копирования».
Теперь Стандарт составляет два правила. Первый предназначен для прямой инициализации и для инициализации копии, где инициализатор имеет тип инициализированного объекта. Второе правило - для инициализации копии в других случаях.
Итак, с этой точки зрения оба термина называются одним - первым - правилом. В случае, когда у вас есть инициализация копии с тем же типом, компилятору разрешается исключить копию, поэтому он может создать созданный вами временный объект непосредственно в инициализированный объект. Таким образом, вы можете очень хорошо сгенерировать тот же код. Но конструктор копирования, даже если копия удалена (оптимизирована), все равно должен быть доступен. Т.е. если у вас есть конструктор личных копий, этот код будет недействительным, если код, в котором он появляется, не имеет к нему доступа.
Второй называется copy-initialization, потому что, если тип инициализатора другого типа, создается временный объект при попытке неявного преобразования правой стороны в левую:
myclass c = 3;
Компилятор создает временный объект типа myclass тогда, когда есть конструктор, который принимает int. Затем он инициализирует объект с этим временным. Также в этом случае созданный временный объект может быть создан непосредственно в инициализированном объекте. Вы можете выполнить эти шаги, печатая сообщения в конструкторах / деструкторах вашего класса и используя опцию -fno-elide-constructors
для GCC. Он не пытается удалить копии тогда.
Кстати, этот код не имеет ничего общего с оператором присваивания. В обоих случаях происходит инициализация.