C ++ 11: как auto работает с инициализатором ()? - PullRequest
0 голосов
/ 13 апреля 2020

Я знаю для C ++ 11 способ инициализации vector с использованием auto, на самом деле std::initializer_list инициализируется вместо vector. Однако, приведенный ниже фрагмент кода:

#include <iostream>
#include <vector>
using namespace std;

int main() {
    auto x = {1, 2};
    cout << typeid(x).name() << endl;
    auto z = (1, 2);
    cout << z << ", type: " << typeid(z).name() << endl;
    return 0;
}

Я не понимаю:

  1. Почему возвращаемый тип x равен St16initializer_listIiE, а тип 'z 'is', используя компилятор g cc -10. Разве мы не должны просто возвращать std::initializer_list и 'int'?
  2. На z: warning: left operand of comma operator has no effect [-Wunused-value] есть предупреждение. Тогда вторая половина результата: 2, type: i. Как c ++ 11 интерпретирует () -инициализированный тип? Почему только последний элемент передается в z и, следовательно, z все еще имеет тип int?

Ответы [ 3 ]

4 голосов
/ 13 апреля 2020

Почему возвращаемым типом x является St16initializer_listI iE, а возвращаемым типом 'z' является 'i' с использованием компилятора g cc -10. Разве мы не должны просто возвращать std :: initializer_list и 'int'?

typeid() напрямую не дадут того, что вы ожидаете, они просто возвращают указанную идентификацию типа c, как записано в своем коде. Если вы хотите расшифровать то же самое, передайте его через c++filt:

c++filt -t St16initializer_listIiE

Это приведет к тому, что вы ожидали, то есть:

std::initializer_list<int>

На z есть предупреждение: предупреждение: левый операнд оператора запятой не действует [-Wunused-value]. Тогда вторая половина результата: 2, введите: i. Как c ++ 11 интерпретирует () -инициализированный тип? Почему в z передается только последний элемент и, следовательно, z по-прежнему имеет тип int?

( ) - это инициализатор, содержащий выражение, или список выражений. Если бы вы присвоили это auto, он бы выбрал самый последний элемент в списке выражений в качестве его типа, поскольку он будет разделен запятыми до появления последнего выражения, которое в идеале говорит auto назначать его тип для последний.

Например:

auto x = (1, 1.5L); 

приведет к длинному.

auto x = (1, 1.5f);

приведет к плавающему.

auto x = (1, "string");

приведет к указателю на константный символ.

Он полностью игнорирует первое значение в инициализаторе ( ), которое является int.

4 голосов
/ 13 апреля 2020

Единственное, что делает список инициализатора - это {}. В

auto z = (1, 2);

у вас есть оператор запятой, который возвращает только последнее значение. Это означает, что ваш код сводится к

auto z = 2;

, а поскольку 2 является int, z является int.

1 голос
/ 13 апреля 2020
  1. Поскольку { 1, 2 } является std::initializer_list<int>, но (1, 2) является выражением, которое расширяется до оператора запятой (он оценивает оба аргумента и возвращает второй, как результат, поэтому (1, 2) свернуто до (2), которое свернуто до 2. Вот почему auto z = (1, 2); приводит к целочисленной инициализации.

  2. Поскольку результат инструкции 1 просто игнорируется (помните, (1, 2) вычисляет оба выражения и выбрасывает результат первого).

...