С С++ 11 мы можем использовать auto a = 1+2
вместо int a = 1+2
, а компилятор сам выводит тип a
. Как это работает? Это медленнее во время компиляции (больше операций), чем объявление типа самостоятельно?
Является ли `auto` спецификатором медленнее во время компиляции?
Ответ 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
привело к беспроигрышной ситуации для кодеров и разработчиков компилятора.