Ключевое слово C ++ auto. Почему это волшебство?

151

Из всего материала, который я использовал для изучения C ++, autoвсегда был странный спецификатор продолжительности хранения, который не служил никакой цели. Но совсем недавно я столкнулся с кодом, который использовал его как имя типа само по себе. Я из любопытства попробовал, и он предполагает тот тип, который я ему назначил!

Внезапно итераторы STL и вообще все, что использует шаблоны, стало в 10 раз легче писать. Такое ощущение, что я использую «забавный» язык вроде Python.

Где это ключевое слово было всю мою жизнь? Сможете ли вы разбить мои мечты, сказав, что это эксклюзивно для Visual Studio или не портативное?

Энн Куинн
источник
19
это не. магия. Он новый ( о нет, какой плохой каламбур ). Теперь будущее за асинхронностью ( вздох )
см.
2
Вот ссылка на ключевые слова auto en.cppreference.com/w/cpp/language/auto
andyqee

Ответы:

157

auto было ключевым словом, которое C ++ «унаследовал» от C, которое существовало почти всегда, но практически никогда не использовалось, потому что было только два возможных условия: либо оно не разрешалось, либо предполагалось по умолчанию.

Использование autoдля обозначения выведенного типа было новым в C ++ 11.

В то же время auto x = initializerвыводит тип xиз типа так initializerже, как вывод типа шаблона работает для шаблонов функций. Рассмотрим такой шаблон функции:

template<class T>
int whatever(T t) { 
    // point A
};

В точке A тип был назначен на Tоснове значения, переданного для параметра whatever. Когда вы это сделаете auto x = initializer;, для определения типа используется тот же вывод xтипа, initializerкоторый используется для его инициализации.

Это означает, что большая часть механизмов вывода типов, которые необходимо реализовать компилятору, autoуже присутствовала и использовалась для шаблонов в любом компиляторе, который даже вроде как пытался реализовать C ++ 98/03. Таким образом, добавление поддержки для autoбыло довольно легко практически для всех команд компиляторов - оно было добавлено довольно быстро, и, похоже, было несколько ошибок, связанных с ним.

Когда этот ответ был первоначально написан (в 2011 году, до того, как высохли чернила в стандарте C ++ 11), он autoбыл уже довольно переносимым. В настоящее время он полностью переносится среди всех основных компиляторов. Единственные очевидные причины, чтобы избежать этого, заключаются в том, что вам нужно написать код, совместимый с компилятором C, или у вас есть конкретная необходимость нацелить какой-то нишевый компилятор, который, как вы знаете, не поддерживает его (например, некоторые люди все еще пишут код для MS-DOS с использованием компиляторов Borland, Watcom и т. д., которые не претерпевали значительных обновлений за последние десятилетия). Если вы используете достаточно актуальную версию любого из основных компиляторов, нет никаких причин избегать ее вообще.

Джерри Гроб
источник
24

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

Николь Болас
источник
Ой! Ага, никогда не думал о C ++ как о языке, который может измениться сам по себе. Мне нужно посмотреть, что еще они добавили в этот C ++ 11, я слышал немного о C ++ 0x, но никогда не копался в нем слишком глубоко.
Энн Куинн
7
@Clairvoire C ++ 0x было временным названием. Он был опубликован в этом месяце и стал C ++ 11.
R. Martinho Fernandes
14

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

Синтаксис

auto variable initializer   (1) (since C++11)

auto function -> return type    (2) (since C++11)

auto function   (3) (since C++14)

decltype(auto) variable initializer (4) (since C++14)

decltype(auto) function (5) (since C++14)

auto :: (6) (concepts TS)

cv(optional) auto ref(optional) parameter   (7) (since C++14)

Объяснение

1) При объявлении переменных в области видимости блока, в области пространства имен, в операторах инициализации циклов for и т. Д. Ключевое слово auto может использоваться в качестве спецификатора типа. Как только тип инициализатора определен, компилятор определяет тип, который заменит ключевое слово auto, используя правила для вывода аргументов шаблона из вызова функции (подробности см. В разделе Вывод аргументов шаблона # Другие контексты). Ключевое слово auto может сопровождаться модификаторами, такими как const или &, которые будут участвовать в выводе типа. Например, данный const auto& i = expr;тип i в точности соответствует типу аргумента u в воображаемом шаблоне, template<class U> void f(const U& u)если вызов функцииf(expr)был составлен. Следовательно, auto && может выводиться либо как ссылка lvalue, либо как ссылка rvalue в соответствии с инициализатором, который используется в цикле for на основе диапазона. Если auto используется для объявления нескольких переменных, выведенные типы должны совпадать. Например, объявление auto i = 0, d = 0.0;сформировано неправильно, в то время как объявление auto i = 0, *p = &i;сформировано правильно, а auto выводится как int.

2) В объявлении функции, использующей синтаксис конечного возвращаемого типа, ключевое слово auto не выполняет автоматическое определение типа. Он служит только частью синтаксиса.

3) В объявлении функции, которое не использует синтаксис конечного возвращаемого типа, ключевое слово auto указывает, что тип возвращаемого значения будет выводиться из операнда его оператора возврата с использованием правил для вывода аргументов шаблона.

4) Если объявленный тип переменной - decltype (auto), ключевое слово auto заменяется выражением (или списком выражений) ее инициализатора, и фактический тип выводится с использованием правил для decltype.

5) Если тип возвращаемого значения функции объявлен decltype (auto), ключевое слово auto заменяется операндом его оператора возврата, и фактический тип возвращаемого значения выводится с использованием правил для decltype.

6) Указатель вложенного имени в форме auto :: является заполнителем, который заменяется классом или типом перечисления в соответствии с правилами вывода заполнителя ограниченного типа.

7) Объявление параметра в лямбда-выражении. (начиная с C ++ 14) Объявление параметра функции. (концепции ТС)

Примечания. До C ++ 11 у auto была семантика спецификатора продолжительности хранения. Смешивание автоматических переменных и функций в одном объявлении auto f() -> int, i = 0;не допускается.

Для получения дополнительной информации: http://en.cppreference.com/w/cpp/language/auto

Prathamesh Aware
источник
11

Этого функционала не было всю вашу жизнь. Он поддерживается в Visual Studio с версии 2010 года. Это новая функция C ++ 11, поэтому она не является эксклюзивной для Visual Studio и будет / будет переносимой. Большинство компиляторов уже поддерживают это.

Р. Мартиньо Фернандес
источник
3

Это никуда не денется ... это новая стандартная функция C ++ в реализации C ++ 11. При этом, хотя это замечательный инструмент для упрощения объявления объектов, а также очистки синтаксиса для определенных парадигм вызовов (например, циклов for на основе диапазона), не злоупотребляйте им :-)

Джейсон
источник
3

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

Это может быть очень полезно, когда нам нужно использовать итератор. Например, для приведенного ниже кода мы можем просто использовать «auto» вместо того, чтобы писать весь синтаксис итератора.

int main() 
{ 

// Initialize set 
set<int> s; 

s.insert(1); 
s.insert(4); 
s.insert(2); 
s.insert(5); 
s.insert(3); 

// iterator pointing to 
// position where 2 is 
auto pos = s.find(3); 

// prints the set elements 
cout << "The set elements after 3 are: "; 
for (auto it = pos; it != s.end(); it++) 
    cout << *it << " "; 

return 0; 
}

Вот как мы можем использовать ключевое слово "авто"

Рахул Гоял
источник
1

Это волшебство - это способность уменьшить необходимость писать код для каждого типа переменной, передаваемого в определенные функции. Рассмотрим функцию print (), аналогичную Python, в базе C.

#include <iostream>
#include <string>
#include <array>

using namespace std;

void print(auto arg) {
     cout<<arg<<" ";
}

int main()
{
  string f = "String";//tok assigned
  int x = 998;
  double a = 4.785;
  string b = "C++ Auto !";
//In an opt-code ASCII token stream would be iterated from tok's as:
  print(a);
  print(b);
  print(x);
  print(f);
}
rodeone2
источник