Есть ли причина использовать ключевое слово auto для С++ 03?
Примечание этот вопрос был первоначально опубликован в 2009 году, прежде чем С++ 11 был ратифицирован и до того, как значение ключевого слова auto
было радикально изменено. Приведенные ответы относятся только к значению С++ 03 auto
- того, что указанный класс хранения, а не значение С++ 11 auto
, - это автоматический вывод типа. Если вы ищете советы о том, когда использовать С++ 11 auto
, этот вопрос не имеет отношения к этому вопросу.
В течение долгого времени я думал, что нет смысла использовать ключевое слово static
в C, потому что переменные, объявленные за пределами области блока, были неявно глобальными. Затем я обнаружил, что объявление переменной как static
в пределах области блока дало бы ей постоянную продолжительность, и объявление ее за пределами области блока (в области программы) дало бы ей область файл (к ней может быть доступ только в этом блоке компиляции).
Итак, это оставляет мне только одно ключевое слово, которое я (возможно) еще не понял полностью: auto
. Есть ли другое значение, кроме "локальной переменной"? Все, что он делает, неявно делается для вас, где бы вы ни хотели его использовать? Как переменная auto
ведет себя в области программы? Что из переменной static auto
в области файлов? Имеет ли это ключевое слово какую-либо цель, кроме только существующей для полноты?
Ответы
Ответ 1
auto
- спецификатор класса хранения, static
, register
и extern
тоже. Вы можете использовать только один из этих четырех в объявлении.
Локальные переменные (без static
) имеют автоматическую продолжительность хранения, что означает, что они живут с самого начала их определения до конца их блока. Помещение авто перед ними избыточно, так как это по умолчанию.
Я не знаю, зачем использовать его в С++. В старых версиях C, которые имеют неявное правило int, вы можете использовать его для объявления переменной
int main(void) { auto i = 1; }
Чтобы сделать его допустимым синтаксисом или disambiguate из выражения присваивания в случае, если i
находится в области видимости. Но это все равно не работает на С++ (вам нужно указать тип). Довольно забавно, стандарт С++ пишет:
Объект, объявленный без спецификатора класса хранения в области блока или объявленный как параметр функции, по умолчанию имеет автоматическую продолжительность хранения. [Примечание: следовательно, авто-спецификатор почти всегда избыточен и не часто используется; одно использование auto заключается в том, чтобы явно отличить оператор объявления от выражения-выражения (6.8). -end note]
Это относится к следующему сценарию, который может быть либо отличным от a
до int, либо объявлением переменной a
типа int
, имеющей избыточные круглые скобки вокруг a
. Он всегда считается объявлением, поэтому auto
не добавит ничего полезного здесь, но вместо этого будет для человека. Но, опять же, человеку было бы лучше снять лишние круглые скобки вокруг a
, я бы сказал.
int(a);
С новым значением auto
, прибывающим с С++ 0x, я бы отговорил использовать его с С++ 03, что означает код.
Ответ 2
В С++ 11 auto
имеет новое значение: он позволяет автоматически выводить тип переменной.
Почему это когда-нибудь полезно? Рассмотрим основной пример:
std::list<int> a;
// fill in a
for (auto it = a.begin(); it != a.end(); ++it) {
// Do stuff here
}
В auto
создается итератор типа std::list<int>::iterator
.
Это может сделать очень сложный код намного легче читать.
Другой пример:
int x, y;
auto f = [&]{ x += y; };
f();
f();
Там auto
вывел тип, необходимый для хранения лямбда-выражения в переменной.
Википедия имеет хороший охват по теме.
Ответ 3
Ключевое слово auto не имеет цели в настоящий момент. Вы совершенно правы, что он просто повторяет класс хранения по умолчанию для локальной переменной, и действительно полезной альтернативой является static
.
Он имеет новый смысл в С++ 0x. Это дает вам некоторое представление о том, насколько бесполезно было!
Ответ 4
GCC имеет специальное использование auto
для вложенных функций - см. здесь.
Если у вас есть вложенная функция, которую вы хотите вызвать до ее определения, вам нужно объявить ее с помощью auto
.
Ответ 5
"auto" предположительно сообщает компилятору решить для себя, куда поместить переменную (память или регистр). Его аналогом является "регистр", который якобы сообщает компилятору попытаться сохранить его в регистре. Современные компиляторы игнорируют оба, поэтому вы тоже должны.
Ответ 6
Я использую это ключевое слово для явного документирования, когда это важно для функции, чтобы переменная была помещена в стек для процессоров на основе стека. Эта функция может потребоваться при изменении стека до возврата из функции (или процедуры обслуживания прерываний).
В этом случае я заявляю:
auto unsigned int auiStack[1]; //variable must be on stack
И затем я получаю доступ за пределами переменной:
#define OFFSET_TO_RETURN_ADDRESS 8 //depends on compiler operation and current automatics
auiStack[OFFSET_TO_RETURN_ADDRESS] = alternate_return_address;
Таким образом, ключевое слово auto
помогает документировать намерение.
Ответ 7
Согласно "Страуструпу", в "языке программирования C" (4-е издание, охватывающем C 11), использование "авто" имеет следующие основные причины (раздел 2.2.2) (слова Stroustrup цитируются):
1)
Определение находится в большой области, где мы хотим сделать тип хорошо видны читателям нашего кода.
С помощью "auto" и необходимого инициализатора мы сможем сразу узнать тип переменной!
2)
Мы хотим быть ясными в отношении диапазона или точности диапазона (например, double, а не float)
По моему мнению, случай, который здесь подходит, выглядит примерно так:
double square(double d)
{
return d*d;
}
int square(int d)
{
return d*d;
}
auto a1 = square(3);
cout << a1 << endl;
a1 = square(3.3);
cout << a1 << endl;
3)
Используя 'auto', мы избегаем избыточности и записи длинных имен типов.
Представьте себе какое-то длинное имя типа из именованного шаблона:
(код из раздела 6.3.6.1)
template<class T> void f1(vector<T>& arg) {
for (typename vector<T>::iterator p = arg.begin(); p != arg.end(); p)
*p = 7;
for (auto p = arg.begin(); p != arg.end(); p)
*p = 7;
}
Ответ 8
В старом компиляторе auto был одним из способов объявить локальную переменную вообще. Вы не можете объявлять локальные переменные в старых компиляторах, таких как Turbo C без ключевого слова auto или некоторых таких.
Ответ 9
Новое значение ключевого слова auto в С++ 0x очень хорошо описано Microsoft Stephan T. Lavavej в свободно просматриваемой/загружаемой видео-лекции по STL, найденной на сайте 9 канала MSDN здесь.
Лекцию стоит посмотреть целиком, но часть ключевого слова auto примерно равна отметке 29-й минуты (приблизительно).
Ответ 10
Есть ли другое значение для "auto", кроме "локальной переменной"?
Не в С++ 03.
Все, что он делает, неявно делается для вас, где бы вы ни захотели его использовать?
Ничего, в С++ 03.
Как автоматическая переменная ведет себя в области программы? Что из статической автоматической переменной в области файлов?
Ключевое слово не допускается вне тела функции/метода.
Имеет ли это ключевое слово какую-либо цель [в С++ 03], отличную от существующей для полноты?
Удивительно, да. Критерии дизайна С++ включали высокую степень обратной совместимости с C. C, имеющим это ключевое слово, и не было реальной причины запретить его или переопределить его значение на С++. Таким образом, целью была одна менее несовместимость с C.
Имеет ли это ключевое слово какую-либо цель в C, отличную от существующей для полноты?
Я узнал об этом только недавно: легкость переноса старых программ из B. C эволюционировала из языка B, синтаксис которого был очень похож на синтаксис C. Однако у B не было никаких типов. Единственный способ объявить переменную в B - указать свой тип хранилища (auto
или extern
). Вот так:
auto i;
Этот синтаксис все еще работает в C и эквивалентен
int i;
поскольку в C класс хранения по умолчанию равен auto
, а по умолчанию используется значение int
. Я предполагаю, что каждая отдельная программа, которая возникла в B и была перенесена на C, была буквально заполнена переменными auto
в то время.
С++ 03 больше не допускает неявный int в стиле C, но он сохранил ключевое слово auto
, не содержащее больше времени, потому что, в отличие от неявного int, не было известно, что он вызывает какие-либо проблемы в синтаксисе С.