Есть ли причина использовать ключевое слово auto в C ++ 03?

85

Обратите внимание, что этот вопрос был первоначально опубликован в 2009 году, до ратификации C ++ 11 и до того, как значение autoключевого слова было радикально изменено. Предоставленные ответы относятся только к значению C ++ 03 auto, которое является указанным классом хранения, а не к значению C ++ 11, autoкоторое является автоматическим выводом типа. Если вам нужен совет о том, когда использовать C ++ 11 auto, этот вопрос не имеет отношения к этому вопросу.

Долгое время я думал, что нет причин использовать staticключевое слово в C, потому что переменные, объявленные вне области видимости блока, были неявно глобальными. Затем я обнаружил, что объявление переменной в staticпределах области видимости блока даст ей постоянную продолжительность, а объявление ее вне области видимости блока (в области программы) даст ей область видимости файла (доступ к которой можно получить только в этом модуле компиляции).

Таким образом, у меня остается только одно ключевое слово, которое я (возможно) еще не полностью понимаю: autoключевое слово. Есть ли у него какое-то другое значение, кроме «локальная переменная»? Что-нибудь, что он делает, что явно не сделано для вас, где бы вы ни захотели его использовать? Как autoпеременная ведет себя в области программы? Что насчет static autoпеременной в области видимости файла? У этого ключевого слова есть какая-либо цель, кроме как просто существовать для полноты ?

Карсон Майерс
источник

Ответы:

74

autoкласс хранения спецификатор static, registerи externтоже. В объявлении можно использовать только один из этих четырех.

Локальные переменные (без static) имеют автоматическую продолжительность хранения, что означает, что они живут с начала своего определения до конца своего блока. Ставить перед ними auto излишне, поскольку в любом случае это значение по умолчанию.

Я не знаю причин использовать его в C ++. В старых версиях C, имеющих неявное правило int, вы могли использовать его для объявления переменной, например:

int main(void) { auto i = 1; }

Чтобы сделать его допустимым синтаксисом или устранить неоднозначность из выражения присваивания в случае, если это iвходит в область действия. Но в C ++ это все равно не работает (нужно указать тип). Как ни странно, стандарт C ++ пишет:

Объект, объявленный без спецификатора класса хранения в области блока или объявленный как параметр функции, по умолчанию имеет автоматическую продолжительность хранения. [Примечание: следовательно, автоматический спецификатор почти всегда избыточен и не часто используется; одно использование auto состоит в том, чтобы явно отличить оператор-объявление от оператора-выражения (6.8). - конец примечания]

который относится к следующему сценарию, который может быть либо приведением aк, intлибо объявлением переменной aтипа intс избыточными круглыми скобками a. Это всегда считается декларацией, поэтому я autoне буду добавлять сюда ничего полезного, но вместо этого добавит для человека. Но опять же, человеку было бы лучше удалить лишние круглые скобки a, я бы сказал:

int(a);

С новым смыслом появления autoC ++ 0x я бы не рекомендовал использовать его со значением C ++ 03 в коде.

Йоханнес Шауб - litb
источник
4
Компиляторы C ++ часто использовали неявные int для возвращаемых значений из функций, еще в дни ARM до стандарта ... До ИМПЕРИИ ...
Дэниел Эрвикер,
1
Я просто распознал это как способ моего компилятора сказать мне, что я забыл объявить функцию вперед-назад. Он сказал бы мне, что мое использование функции отличалось от того, как она была объявлена, из-за неявного int.
Carson Myers
29
Самое приятное то, что программисты писали «авто» (четыре буквы), чтобы не писать «int» (три буквы).
Макс Либберт,
30
@Max - эй, многие люди говорят «дабл-у-дабл-у-дабл-у» как аббревиатуру «всемирной паутины».
Дэниел Эрвикер,
3
@smichak нет, volatile - это квалификатор типа. Вместо того, чтобы определять, где хранить значение, он изменяет поведение записи и чтения из объекта квалифицированного типа volatile. Могут быть изменчивые квалифицированные переменные стека (класс автоматического хранения), а также переменные продолжительности статического хранения с изменяемыми характеристиками (локальный «статический» класс хранения, нелокальные переменные). Кроме того, я не знаю, является ли «
изменяемый
86

В C ++ 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выведен тип, необходимый для хранения лямбда-выражения в переменной. Википедия хорошо освещает эту тему.

std''OrgnlDave
источник
4
Все еще не уверен, что это хорошее использование авто. Код должен быть легким для чтения, а не для написания!
DanDan
38
Не знаю, как вы, но я считаю, что это намного легче читать, чем спам типа итератора.
Overv
17
И если по какой-то причине вы решите изменить класс из list <int> на какой-то другой класс, вам не нужно искать каждое объявление итератора и изменять его.
roslav
2
@KarateSnowMachine: если вам нужна константа, вы должны использовать «const auto» вместо «auto».
darth happyface
4
@darth const auto it = a.begin();даст вам const iterator, а не a const_iterator. Вы все равно можете изменить элемент, но ++itне сможете скомпилировать. Чтобы получить a const_iterator, вы должны использоватьauto it = a.cbegin();
fredoverflow
35

Ключевое слово auto на данный момент не имеет смысла. Вы совершенно правы, что он просто повторно устанавливает класс хранения по умолчанию для локальной переменной, что является действительно полезной альтернативой static.

В C ++ 0x он имеет совершенно новое значение . Это дает вам некоторое представление о том, насколько это было бесполезно!

Дэниел Эрвикер
источник
1
о человек, это когда-либо бесполезно. Но мне нравится новый смысл. Это делает некоторый код менее подробным и избыточным.
Carson Myers
Да, использование эквивалента в C #, вероятно, будет иметь огромное значение. Тем более в C ++, если вы используете шаблоны выражений, типы которых настолько сложны, что никогда не предназначались для написания вручную.
Дэниел Эрвикер,
7

GCC имеет специальное использование autoдля вложенных функций - см. Здесь .

Если у вас есть вложенная функция, которую вы хотите вызвать до ее определения, вам нужно объявить ее с помощью auto.

qrdl
источник
это отличная, хотя и зависит от компилятора, реализация auto. Спасибо за исследование :)
Carson Myers
3

"auto" якобы указывает компилятору самому решить, куда поместить переменную (память или регистр). Его аналог - «регистр», который якобы указывает компилятору попытаться сохранить его в регистре. Современные компиляторы игнорируют и то, и другое, так что вы должны тоже.

ТЕД
источник
1
Не совсем так - если вы объявите его с помощью "register", компиляторы не позволят вам использовать оператор адресации (& foo) для переменной, потому что, ну, он не существует нигде в памяти (и, следовательно, не имеет адреса).
Тим Час
3

Я использую это ключевое слово для явного документирования, когда для функции критично размещение переменной в стеке для стековых процессоров. Эта функция может потребоваться при изменении стека перед возвратом из функции (или подпрограммы обслуживания прерывания). В этом случае заявляю:

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ключевое слово помогает документировать намерение.

Люк
источник
Я предполагаю, что это всего лишь сигнал о намерении, поскольку ключевое слово на самом деле не обеспечивает размещение стека, а не просто его пропуск.
underscore_d
2

Согласно Страуструпу, в «Языке программирования C» (4-е издание, охватывающее C 11) использование слова «auto» имеет следующие основные причины (раздел 2.2.2) (слова Страуструпа цитируются):

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;
}
Wesley.mesquita
источник
1

В старом компиляторе auto был одним из способов вообще объявить локальную переменную. Вы не можете объявлять локальные переменные в старых компиляторах, таких как Turbo C, без ключевого слова auto или чего-то подобного.

Чаз
источник
1

Новое значение ключевого слова auto в C ++ 0x очень хорошо описано Стефаном Т. Лававей из Microsoft в видеолекции по STL, которую можно бесплатно просмотреть / загрузить, которую можно найти на сайте MSDN Channel 9 здесь .

Лекцию стоит просмотреть целиком, но часть ключевого слова auto находится примерно на 29-й минуте (приблизительно).

Sabuncu
источник
0

Есть ли у слова «авто» другое значение, кроме «локальная переменная»?

Не в C ++ 03.

Что-нибудь, что он делает, что явно не сделано для вас, где бы вы ни захотели его использовать?

Вообще ничего, в C ++ 03.

Как автоматическая переменная ведет себя в области программы? Что насчет статической автоматической переменной в области видимости файла?

Ключевое слово запрещено за пределами тела функции / метода.

Есть ли у этого ключевого слова какую-либо цель [в C ++ 03], кроме как просто существовать для полноты?

Удивительно, но да. Критерии разработки C ++ включают высокую степень обратной совместимости с C. В C было это ключевое слово, и не было реальной причины запрещать его или переопределять его значение в C ++. Итак, целью было на одну несовместимость с C.

Есть ли у этого ключевого слова какую-либо цель в C, кроме как просто существовать для полноты?

Я только недавно узнал об одном: простота переноса древних программ с B. C произошел от языка B, синтаксис которого был очень похож на C. Однако B не имел никаких типов. Единственный способ объявить переменную в B - указать ее тип хранения ( autoили extern). Как это:

авто я;

Этот синтаксис все еще работает в C и эквивалентен

int i;

поскольку в C по умолчанию используется класс хранения auto, а по умолчанию - тип int. Я предполагаю, что каждая отдельная программа, которая возникла в B и была перенесена на C, autoв то время была буквально полна переменных.

C ++ 03 больше не допускает неявного int в стиле C, но сохранил autoключевое слово no-more-точно-полезное, потому что, в отличие от неявного int, не было известно, что оно вызывает какие-либо проблемы в синтаксисе C.

Йирка Ханика
источник