Копирование и перемещение элементов списка инициализации
#include <iostream>
struct A {
A() { std::cout << 1; }
A(const A&) { std::cout << 2; }
A(A&&) { std::cout << 3; }
};
void foo(auto l) {}
int main() {
auto l = {A{}};
foo(l);
foo(std::move(l));
}
Почему программа печатает 1, а не 123 или другую комбинацию? Какие конструкторы вызываются и почему?
Ответы (1 шт):
Если закрыть глаза на то, что clang не компилирует, а gcc - да, но с ворнингами, то на самом деле можно считать, что функция foo выглядит так
template<typename T>
void foo(T l) {}
(мы же знаем, что в большинстве случаев для auto способ вывода типов подобен шаблонному, поэтому, такая замена допустима).
Осталось выяснить, а какой же тип у l? А тут не все так очевидно. Он там std::initializer_list<A>. И при инициализации единственного его аргумента и вызывается конструктор по умолчанию.
Теперь можно понять и настоящую сигнатуру функции foo
void foo<std::initializer_list<A> >(std::initializer_list<A>)
(взято с недр ассемблерного кода, который сгенерировал gcc) и эта сигнатура соответствует тому, что и ожидалось вначале.
Теперь смотрим в документацию https://en.cppreference.com/w/cpp/utility/initializer_list
Initializer lists may be implemented as a pair of pointers or pointer and length. Copying a std::initializer_list does not copy the underlying objects.
и выделенное будет ответом.