Новое ключевое слово "auto"; когда оно должно использоваться для объявления типа переменной? [дубликат]
Возможные Дубликаты:
сколько это слишком много с C++0x auto ключевое слово
имеем ли мы (как сообщество) достаточно опыта, чтобы определить, когда и/или злоупотребляют ли авто?
то, что я действительно ищу, - это руководство по лучшей практике
- когда использовать auto
- когда этого следует избегать
простые эмпирические правила, которым можно быстро следовать в 80% случаев случаи.
в качестве контекста этот вопрос вызван моим ответом здесь
6 ответов:
я думаю, когда тип является очень популярным среди со-программистов, которые работают (или будут работать) в ваш проект, то
auto
можно использовать, например, в следующем коде://good : auto increases readability here for(auto it = v.begin(); it != v.end(); ++it) //v is some [std] container { //.. }
или
//good : auto increases readability here for(auto it = std::begin(v); it != std::end(v); ++it)//v could be array as well { //.. }
но когда тип не очень хорошо известен и нечасто используется , то я думаю
auto
кажется, чтобы уменьшить читаемость, например, здесь://bad : auto decreases readability here auto obj = ProcessData(someVariables);
в то время как в первом случае, использование
auto
кажется очень хорошим и не уменьшает читабельность, и поэтому, смогите быть использовано обширно, но в последнем случае, оно уменьшает читабельность и следовательно не должно быть использовано.
другое место, где
auto
может использоваться, когда вы используетеnew
1 илиmake_*
функции , такие как здесь://without auto. Not that good, looks cumbersome SomeType<OtherType>::SomeOtherType * obj1 = new SomeType<OtherType>::SomeOtherType(); std::shared_ptr<XyzType> obj2 = std::make_shared<XyzType>(args...); std::unique_ptr<XyzType> obj2 = std::make_unique<XyzType>(args...); //With auto. good : auto increases readability here auto obj1 = new SomeType<OtherType>::SomeOtherType(); auto obj2 = std::make_shared<XyzType>(args...); auto obj3 = std::make_unique<XyzType>(args...);
здесь это очень хорошо, так как это уменьшает использование клавиатуры, не уменьшая читаемость, так как любой может знать тип объекты создается, просто глядя на код.
1. Избегайте использования
new
и raw-указатели, хотя.
иногда тип настолько неуместен, что знание типа даже не требуется, например, в шаблон выражения; в самом деле, практически невозможно написать тип (правильно), в таких случаях
auto
облегчение для программистов. Я написал библиотеку шаблонов выражений, которые могут быть использованы как:foam::composition::expression<int> x; auto s = x * x; //square auto c = x * x * x; //cube for(int i = 0; i < 5 ; i++ ) std::cout << s(i) << ", " << c(i) << std::endl;
выход:
0, 0 1, 1 4, 8 9, 27 16, 64
теперь сравните приведенный выше код следующим эквивалентно код, который не использует
auto
:foam::composition::expression<int> x; //scroll horizontally to see the complete type!! foam::composition::expression<foam::composition::details::binary_expression<foam::composition::expression<int>, foam::composition::expression<int>, foam::operators::multiply>> s = x * x; //square foam::composition::expression<foam::composition::details::binary_expression<foam::composition::expression<foam::composition::details::binary_expression<foam::composition::expression<int>, foam::composition::expression<int>, foam::operators::multiply> >, foam::composition::expression<int>, foam::operators::multiply>> c = x * x * x; //cube for(int i = 0; i < 5 ; i++ ) std::cout << s(i) << ", " << c(i) << std::endl;
Как видите, в таких случаях
auto
делает вашу жизнь легче в геометрической прогрессии. Выражения, используемые выше, очень просты; подумайте о типе некоторых более сложных выражений:auto a = x * x - 4 * x + 4; auto b = x * (x + 10) / ( x * x+ 12 ); auto c = (x ^ 4 + x ^ 3 + x ^ 2 + x + 100 ) / ( x ^ 2 + 10 );
тип таких выражений был бы еще более огромным и уродливым, но благодаря
auto
, теперь мы можем позволить компилятору вывести тип выражения.
Итак, нижняя линия: ключевое слово
auto
может увеличение или уменьшение ясность и читаемость вашего кода,в зависимости от контекста. Если контекст дает понять, что тип это или, по крайней мере, как он должен использоваться (в случае стандартного итератора контейнера) или знание фактического типа даже не требуется (например, в шаблонах выражений), тоauto
должно быть используется, и если контекст не делает его ясным и не очень распространен (например, второй случай выше), то лучше быть избежать.
легко. Используйте его, когда вы не важно что это за тип. Например
for (auto i : some_container) { ...
все, что меня здесь волнует, это
i
- Это все, что находится в контейнере.это немного похоже на typedefs.
typedef float Height; typedef double Weight; //.... Height h; Weight w;
вот, мне все равно
h
иw
поплавки или двойники, только что они любой тип подходит для выражения высоты и веса.или считать
for (auto i = some_container .begin (); ...
здесь все, что меня волнует, это то, что это подходящий итератор, поддерживающий
operator++()
, это вроде как утка набрав в этом отношении.также тип лямбд не может быть записан, так что
auto f = []...
хороший стиль. Альтернативой является приведение кstd::function
но это идет с накладными расходами.Я действительно не могу представить себе "злоупотребление"
auto
. Самое близкое, что я могу себе представить, это лишение себя явного преобразования в какой-то значимый тип-но вы бы не использовалиauto
для этого ты создать объект нужного типа.если вы можете удалить избыточность в коде без побочных эффектов, то это должны будьте добры сделать это.
Я бы применил то же правило, что и для
var
в C#: использовать его либерально. Это увеличение читабельности. Если тип переменной, на самом деле достаточно важным, чтобы быть четко указано, в каких случаях это следует делать (дух).тем не менее, я утверждаю, что (особенно в статически типизированных языках) компилятор намного лучше отслеживает типы для нас, чем мы. Большую часть времени точно тип не очень важно в любом случае (в противном случае интерфейсы не будут работать на практике). Более важно знать, какие операции разрешены. Контекст должен нам это сказать.
кроме того,
auto
на самом деле сможете предотвращение ошибок, предотвращая нежелательные неявные преобразования в инициализации. В общем, утверждениеFoo x = y;
будет выполнять неявное преобразование, еслиy
не типаFoo
и неявное преобразование существует. Это является причиной, чтобы избежать неявных преобразований в первое место. К сожалению, в C++ их уже слишком много.писать
auto x = y;
предотвратит эту проблему в принципе.С другой стороны, должно быть ясно, что когда я выполняю вычисления, которые предполагают то или иное количество байтов в целом, явный тип переменной должен быть известен и должен быть четко указан.
Не все случаи так ясно, но я утверждаю, что большинство из них, и это
- в большинстве случаев легко увидеть, должен ли быть известен явный тип, и
- потребность в явных типах сравнительно редка.
Эрик Липперт, основной разработчик в команде компилятора C#,заявил Почти то же самое в отношении
var
.
я думаю, что ответ на ваш первый вопрос вроде нет. Мы знаем достаточно, чтобы собрать некоторые рекомендации о том, когда использовать или избегать
auto
, но они все еще оставляют довольно много случаев, когда лучшее, что мы можем сейчас сказать, это то, что мы пока не можем дать много объективных советов о них.очевидный случай, когда вы почти есть чтобы использовать его в шаблоне, когда вы хотите (например) правильный тип для хранения результата некоторой операции на двух универсальный параметр. В таком случае единственная возможность злоупотребления на самом деле не будет злоупотреблением
auto
сам, но будь то общий тип операции, которую вы делаете (или тип шаблона, который вы пишете и т. д.) это то, что вам лучше избегать.есть также по крайней мере несколько ситуаций, когда вам явно нужно избегать
auto
. Если вы используете что-то вроде прокси-типа, где вы зависите от преобразования из прокси - >target, чтобы сделать часть работы под рукой,auto
будет (попытка) создать цель того же типа, что и источник, чтобы преобразование не произошло. В некоторых случаях это может просто задержать преобразование, но в других оно вообще не будет работать (например, если тип прокси не поддерживает назначение, что часто бывает).Другим примером может быть, когда вам нужно убедиться, что конкретная переменная имеет определенный тип ради чего-то вроде внешнего интерфейса. Например, рассмотрите возможность применения маски сети к IP-адрес (v4). Для аргументации предположим, что вы работаете с отдельными октетами адреса (например, представляя каждый как
unsigned char
), поэтому мы в конечном итоге с чем-то вродеoctets[0] & mask[0]
. Благодаря правилам продвижения типа C, даже если оба операндаunsigned char
С, результат, как правило, будетint
. Мы нужно результат должен бытьunsigned char
хотя (т. е. один октет) неint
(обычно 4 октета), хоть. Как таковой, в данной ситуации,auto
почти конечно, неуместно.это все еще оставляет много случаев, когда это решение вызова, хотя. Мой собственный тенденция для таких случаев стоит лечить
auto
по умолчанию, и использовать только явный тип в случаях, которые по крайней мере немного похожи на последний случай, который я привел выше-даже если конкретный тип не нужны для правильной работы, что я действительно люблю!--15-->хочу определенный тип, даже если это может включать неявный преобразование.моя догадка (но это всего лишь догадка) заключается в том, что со временем я буду наверное как правило, еще больше в этом направлении. По мере того, как я привыкаю к компилятору, выбирающему типы, я обнаружу, что довольно много случаев, когда я в настоящее время думаю я должен указать тип, я действительно не нужно, и код будет просто отлично.
я подозреваю, что многие из нас (и чем старше/опытнее мы, вероятно, тем хуже мы будем об этом) будут используйте явные типы по причинам, которые в конечном счете ведут к некоторому чувству о производительности и вере в то, что наш выбор улучшит производительность. Часть времени мы мая даже быть правым - но как большинство из нас с таким большим опытом обнаружили, наши догадки часто ошибочны (особенно когда они основаны на неявных предположениях), и компиляторы и процессоры, как правило, становятся лучше в таких вещах с течением времени, а также.
я использовал языки с полным выводом типа. Я не вижу причин не ставить
auto
везде это технически возможно*. На самом деле я уже писалauto i = 0;
, гдеint
- это один символ короче, чемauto
. Я даже не уверен, что сделал это, потому что внизу: мне не нравится печатать манифест.*: например
auto int[] = { 0, 1, 2, 3 }
не работает.