Как отметил Никол Болас, исходная версия этого ответа была неправильной: cppreference на момент написания неправильно документировал порядок, в котором конструкторы рассматривались в инициализации списка. Ниже приведен ответ с использованием правил, поскольку они существуют в черновом проекте стандарта n4140, который очень близок к официальному стандарту C ++ 14.
Текст оригинала ответ все еще включен для записи.
В комментарии к NathanOliver, gcc и clang производят разные выходы в этой ситуации:
g++ -std=c++14 -Wall -pedantic -pthread main.cpp && ./a.out
default ctor
copy ctor
copy ctor
initializer list
clang++ -std=c++14 -Wall -pedantic -pthread main.cpp && ./a.out
default ctor
copy ctor
copy ctor
gcc верен.
n4140 [dcl.init.list] / 1
Инициализация списка - это инициализация объекта или ссылки из скопированного списка init.
Вы используете там инициализацию списка, а поскольку
c
является объектом, правила его инициализации списка определены в [dcl.init.list] / 3:[dcl.init.list] / 3:
Список-инициализация объекта или ссылки типа T определяется следующим образом:
blockquote>
- Если
T
является агрегатом ...- В противном случае, если в списке инициализаторов нет элементов ...
- В противном случае, если
T
является специализациейstd::initializer_list
..., проходящий через список:
Foo
не является агрегатом.- Он имеет один элемент .
Foo
не является специализациейstd::initializer_list
.Затем мы нажимаем [dcl.init.list] /3.4:
В противном случае, если
blockquote>T
является типом класса, рассматриваются конструкторы. Применяемые конструкторы перечисляются, а лучший выбирается с помощью разрешения перегрузки (13.3, 13.3.1.7). Если для преобразования любого из аргументов требуется сужение преобразования (см. Ниже), программа плохо сформирована.Теперь мы куда-то попадаем. 13.3.1.7 также известен как [over.match.list]:
Инициализация с помощью инициализации списка Когда объекты неагрегатного типа класса
T
инициализируются по списку (8.5.4) , разрешение перегрузки выбирает конструктор в две фазы:blockquote>
- Первоначально функции-кандидаты являются конструкторами-списками инициализаторов (8.5.4) класса
T
, а список аргументов состоит из инициализатора список как один аргумент.- Если не найдено никакого жизнеспособного конструктора-списка инициализатора, разрешение перегрузки выполняется снова, где кандидатные функции являются всеми конструкторами класса
T
, а список аргументов состоит из элементов списка инициализаторов.Таким образом, конструктор копирования будет считаться только после конструкторов списка инициализаторов во второй фазе разрешения перегрузки. Здесь должен использоваться конструктор списка инициализаторов.
Стоит отметить, что [over.match.list] затем продолжается:
Если в списке инициализаторов нет элементов и
blockquote>T
имеет конструктор по умолчанию, первая фаза опущена. В инициализации списка копий, если выбран явный конструктор, инициализация плохо сформирована.и что после [dcl.init.list] /3.5 имеет дело с одноэлементной инициализацией списка :
В противном случае, если в списке инициализаций имеется один элемент типа
blockquote>E
, а такжеT
не является ссылочным типом или его ссылочный тип ссылается на ссылкуE
, объект или ссылка инициализируются из этого элемента; если для преобразования элемента вT
требуется преобразование сужения (см. ниже), программа плохо сформирована., которая объясняет, где cppreference получил свой специальный случай для одноэлементного списка инициализация, хотя они поместили ее выше в порядке, чем это должно быть.
Оригинальный ответ
Вы сталкиваетесь с интересным аспектом инициализации списка, где, если список выполняется некоторые требования к нему могут рассматриваться как инициализация копирования, а не инициализация списка.
из cppreference :
Эффекты инициализации списка объекта типа
T
являются:Если
blockquote>T
- тип класса, а в списке инициализаций имеется один элемент того же или производного типа (возможно, cv-qualified), объект инициализируется из этого элемента (путем инициализации копирования для инициализации списка копий или путем прямой инициализации для инициализации прямого списка). (поскольку c ++ 14)
Foo c{b}
выполняет все эти требования.
Wireshark является одним из лучших инструментов для получения и анализа трафика IP.
Вид [Редактирования] Ламе, на который Вы ответили сначала и не получили галочку. Я не означал протягивать Вас. +1 как утешение.
Я настоятельно рекомендую Wireshark для анализа трафика.