С cppreference.com :
В противном случае конструкторы T
рассматриваются в два этапа:
Все конструкторы, которые принимают std::initializer_list
в качестве единственного аргумента или в качестве первого аргумента, если оставшиеся аргументы имеют значения по умолчанию, проверяются и сопоставляются по разрешению перегрузки с одним аргументом типа std::initializer_list
Если предыдущий этап не дает совпадения, все конструкторы T
участвуют в разрешении перегрузки для набора аргументов, который состоит из элементов braced-init-list , сограничение, что разрешены только не сужающие преобразования.Если на этом этапе создается явный конструктор как наилучшее совпадение для copy-list-initialization , компиляция завершается неудачно (обратите внимание, что в простом copy-initialization явные конструкторы вообще не рассматриваются).
В вашем случае
string(4, 'c')
использует следующий конструктор.
std::string(size_type count,
char ch,
const Allocator& alloc = Allocator() );
С другой стороны,
string{ 4, 'c' }
использует следующий конструктор.
std::string(std::initializer_list<char> ilist,
const Allocator& alloc = Allocator() );
Если бы второй конструктор не был определен в std::string
, обаиз них были бы произведены идентичные объекты.