Является ли `auto` спецификатором медленнее во время компиляции?

С С++ 11 мы можем использовать auto a = 1+2 вместо int a = 1+2, а компилятор сам выводит тип a. Как это работает? Это медленнее во время компиляции (больше операций), чем объявление типа самостоятельно?

Ответ 1

auto просит компилятор С++ 11 сделать некоторый ограниченный тип вывода (загляните в Ocaml, если вы хотите получить более сексуальный язык вывода типа). Но накладные расходы - это только время компиляции.

Если вы замените auto a=1+2; на int a=1+2; (оба имеют то же значение, см. answer by simpleicis), и если вы спросите своего компилятора optimize (и, возможно, даже без запроса оптимизации), вы, вероятно, получите ту же machine код. См. Также .

Если вы используете GCC, попробуйте скомпилировать небольшой файл С++ 11 foo.cc с g++ -Wall -fverbose-asm -O -S foo.cc и посмотреть (с редактор) в сгенерированный файл ассемблера foo.s. Вы не увидите разницы в сгенерированном коде (но файл ассемблера может немного измениться, например, из-за метаданных, таких как отладочная информация и т.д.)

Если вы обеспокоены более медленным временем компиляции, я полагаю, что использование auto не является решающим фактором (возможно, перегрузка может быть более дорогостоящей во время компиляции). С++ 11 почти разработан, чтобы практически потребовать много оптимизаций (в частности, сложная вставка и постоянная сворачивание и удаление мертвого кода), и ее "разбор" (особенно включение заголовка и расширение шаблона) является дорогостоящим.

Предварительная компиляция заголовков и параллельная сборка с make -j (и, возможно, ccache или distcc) может помочь улучшить общее время компиляции, намного больше, чем избегать auto.

И если вы хотите систематически избегать auto (в частности, в range-for петли вроде std::map<std::string,int> dict; for (auto it: dict) {... }), вы в конечном итоге набрали гораздо больше исходного кода (чей синтаксический анализ и проверка занимает значительное время) с большим риском ошибки. Как объяснено здесь, вы можете немного ошибиться, тип и объяснение (немного ошибочно) могут замедлить выполнение вашего кода из-за дополнительных преобразований.

Если вы используете GCC, вы можете передать -ftime-report до g++ и получить измерения времени о различных проходах и фазах GCC.

Ответ 2

Компилятор знает тип, на который оценивается выражение (например, 1 + 2). Это так, как работает язык - оба операнда имеют тип int, поэтому результат равно int. С помощью auto a вы просто сообщаете компилятору "использовать тип инициализирующего выражения".

Компилятор не должен выполнять какую-либо дополнительную работу или выводить здесь. Ключевое слово auto просто освобождает вас от определения выражения и написания правильного типа. (Что вы можете ошибаться, возможно, непредвиденные побочные эффекты - см. этот вопросверхний ответ) для примера, как auto может избежать непреднамеренных преобразований времени выполнения и копирования.


Ключевое слово auto действительно приходит в себя с итераторами:

std::vector< std::string >::const_iterator it = foo.cbegin();

против

auto it = foo.cbegin();

Ответ 3

Как это работает:

Из ISO/IEC:

... Авто-спецификатор является заполнителем для типа, который будет выведен (7.1.6.4). Другие спецификаторы простого типа указывают либо ранее объявленный пользовательский тип, либо один из основных типов...

7.1.6.4 авто-спецификатор

  • Автоматический тип-спецификатор означает, что тип объявляемой переменной должен быть выведен из его инициализатора или что декларатор функции должен включать тип возвращаемого типа возврата.
  • Автотип-спецификатор может отображаться с объявлением функции с типом возвращаемого типа в любом контекст, в котором такой декларатор действителен.
  • В противном случае тип переменной выводится из ее инициализатора. Имя объявляемой переменной не должны появляться в выражении инициализатора. Это использование авто допускается при объявлении переменных в блок, в области пространства имен и в for-init-statement; auto будет отображаться как один из спецификаторов decl в spec-specifier-seq, а за спецификатором-seq должен следовать один или несколько initdeclarators, каждый из которых должен иметь непустой инициализатор...

Пример:

auto x = 5; // OK: x has type int
const auto *v = &x, u = 6; // OK: v has type const int*, u has type const int
static auto y = 0.0; // OK: y has type double
auto int r; // error: auto is not a storage-class-specifier

Быстрее ли это:

Простой ответ Да, используя его, многие типы преобразований могут быть опущены, однако, если их не использовать должным образом, это может стать большим источником ошибок.

В одном из интервью Бьярне Страуструпа он сказал, что ключевое слово auto привело к беспроигрышной ситуации для кодеров и разработчиков компилятора.