Почему std::vector<T> v{1, 2, 3} и std::vector<T> v = {1, 2, 3} вызывают разные конструкторы, когда T неявно преобразуетC++

Программы на C++. Форум разработчиков
Ответить Пред. темаСлед. тема
Anonymous
 Почему std::vector<T> v{1, 2, 3} и std::vector<T> v = {1, 2, 3} вызывают разные конструкторы, когда T неявно преобразует

Сообщение Anonymous »

Вопрос- см. Компилятор Explorer
Если я создаю std :: vector и инициализации его двумя способами, оба вызывают std :: initializer_list Конструктор. < /p>

Код: Выделить всё

std::vector  v1{1, 2, 3};     // Calls vector(initializer_list< int >)
std::vector  v2 = {1, 2, 3};  // Calls vector(initializer_list< int >)
Но если я использую класс, который неявно преобразует из int:

Код: Выделить всё

struct Imp { Imp(int) {} };
Затем второй метод инициализации вызывает конструктор, который принимает пару итераторов.

Код: Выделить всё

std::vector  v3{1, 2, 3};     // Calls vector(initializer_list< Imp >)
std::vector  v4 = {1, 2, 3};  // Calls vector(const int*, const int* ) ???
Это происходит только с помощью gcc 14.2 . При использовании clang 19.1 или MSVC 19.40 , как V3 , так и V4 вызовите конструкцию initializer_list . Уровень оптимизации не имеет значения
Почему = {} синтаксический вектор вызова (const int*, const int*) на GCC?
Дальнейшее исследование < /h2>
Я попытался создать свой собственный шаблон класса, который имеет оба конструктора: < /p>

Код: Выделить всё

template 
struct Custom {
Custom(std::initializer_list) {}
Custom(const int*, const int*)   {}
};
Теперь оба {} и = {} Синтаксис вызовите конструктор initializer_list на GCC.

Код: Выделить всё

Custom       v5{1, 2, 3};     // Calls Custom(initializer_list< Imp >)
Custom       v6 = {1, 2, 3};  // Calls Custom(initializer_list< Imp >)
Что действительно запутывает, так это то, что я специализируюсь на std::vector для своего неявно преобразующего типа Imp. Тогда есть три случая:
Случай 1 — предоставить только инициализатор_list ctor

Код: Выделить всё

template 
struct std::vector {
vector(initializer_list)   {}
};
Результат — оба синтаксиса вызывают предоставленный ctor

Код: Выделить всё

std::vector v7{1, 2, 3};      // Calls vector(initializer_list< Imp >)
std::vector v8 = {1, 2, 3};   // Calls vector(initializer_list< Imp >)
case 2 - предоставление const int* только ctor

Код: Выделить всё

template 
struct std::vector {
vector(const int*, const int*)   {}
};
result - оба синтаксиса не могут компилироваться (без сопоставления ctor)

Код: Выделить всё

std::vector v9{1, 2, 3};      // Error - no matching ctor
std::vector vA = {1, 2, 3};   // Error - no matching ctor
case 3 - предоставить оба CTOR

Код: Выделить всё

template 
struct std::vector {
vector(initializer_list)    {}
vector(const int*, const int*)   {}
};
result - {} syntax вызывает на вызывает initializer_list ctor, в то время как = {} < /code> Syntax вызывает Const int* ctor

Код: Выделить всё

std::vector vB{1, 2, 3};      // Calls vector(initializer_list< Imp >)
std::vector vC = {1, 2, 3};   // Calls vector(const int*, const int*) ???
< /code>
Вот где я потерян.

в  [b] case 3 < /strong> < /em>, как Предоставление инициализатора_листа 
конструктора разрешить конструктор const int* конструктор? Знайте, какой конструктор называется. Это началось, когда я смотрел, когда называются конструкторы Copy vs. Move. std :: initializer_list не может быть перенесен из. Но вот несколько дополнительных примеров, с отпечатками.

Код: Выделить всё

struct Imp { Imp(int) {} };

template 
struct Custom {
Custom(std::initializer_list)    { std::printf("initializer_list\n");    }
Custom(const int*, const int*)      { std::printf("const int*, const int*\n"); }
};

int main(int argc, char *argv[]) {
Custom     v{1, 2, 3};
Custom     w = {1, 2, 3};
Печать:

Код: Выделить всё

initializer_list
initializer_list
Пример 2 [/b] - с использованием std :: векторная специализация

Код: Выделить всё

struct Imp { Imp(int) {} };

template 
struct std::vector {
vector(initializer_list)       { std::printf("initializer_list\n");    }
vector(const int*, const int*)      { std::printf("const int*, const int*\n"); }
};

int main(int argc, char *argv[]) {
std::vector    v{1, 2, 3};
std::vector    w = {1, 2, 3};
Печать:

Код: Выделить всё

initializer_list
const int*, const int*
Разница между двумя примерами - это то, что один - это std :: specialization, а другая - нет.

Почему это изменяет, как называется перегрузка CTOR? Vector со строкой литералы много раз, используя v {} и v = {} синтаксисы.
на моем i9- 10885H:
gcc 14.2

Код: Выделить всё

v{}   0.820 seconds
v={}  0.444 seconds
v={} took 54.1% as long as v{}
clang 18.1

Код: Выделить всё

v{}   0.819 seconds
v={}  0.842 seconds
v={} took 102.8% as long as v{}
Похоже, что это оптимизация строкового литерала в GCC, которая работает только для синтаксиса v = {.


Подробнее здесь: https://stackoverflow.com/questions/793 ... -different
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C++»