Я использовал новое auto
ключевое слово, доступное в стандарте C ++ 11 для сложных шаблонных типов, для которого, как мне кажется, оно было разработано. Но я также использую его для таких вещей, как:
auto foo = std::make_shared<Foo>();
И более скептически для:
auto foo = bla(); // where bla() return a shared_ptr<Foo>
Я не видел много дискуссий на эту тему. Кажется, это auto
может быть использовано слишком часто, поскольку тип часто является формой проверки документации и проверки работоспособности. Где вы проводите черту при использовании auto
и каковы рекомендуемые варианты использования этой новой функции?
Чтобы уточнить: я не спрашиваю философское мнение; Я спрашиваю о предполагаемом использовании этого ключевого слова стандартным комитетом, возможно, с комментариями о том, как это предполагаемое использование реализуется на практике.
Примечание: этот вопрос был перемещен в SE.Programmers, а затем обратно в переполнение стека. Обсуждение этого можно найти в этом мета-вопросе .
auto
ключевое слово, то вы знаете, как оно должно использоваться. Это то, что я спрашиваю, как кто-то новичок в этой функции, как я должен ее использовать?var
(то есть, когда люди перестали думать, что это не динамическая типизация, в конце концов). Если вы хотите, вы можете начать с этого вопроса и перейти к соответствующим вопросам.auto foo = bla();
«плохим» - это, несомненно, мнение, а не факт, который ставит этот вопрос и отвечает на обсуждение, что делает его актуальным для программистов SE, что и есть то, что указывают голоса при закрытии. /Ответы:
Я думаю, что
auto
ключевое слово следует использовать всякий раз, когда трудно сказать, как писать тип с первого взгляда, но тип правой части выражения очевиден. Например, используя:чтобы ввести составной ключ
boost::multi_index
, даже если вы знаете, что это такint
. Вы не можете просто написать,int
потому что это может быть изменено в будущем. Я бы написалauto
в этом случае.Поэтому, если
auto
ключевое слово улучшает читабельность в конкретном случае, используйте его. Вы можете написать,auto
когда для читателя очевидно, какой типauto
представляет.Вот некоторые примеры:
источник
bla()
вы отдаете все , что возвращаетеfoo
.Используйте
auto
везде, где можете, особенно,const auto
чтобы побочные эффекты не вызывали беспокойства. Вам не придется беспокоиться о типах, за исключением очевидных случаев, но они все равно будут статически проверены для вас, и вы можете избежать повторения. Там, гдеauto
это невозможно, вы можете использоватьdecltype
для семантического выражения типов как контрактов на основе выражений. Ваш код будет выглядеть по-другому, но это будет положительное изменение.источник
auto&&
в сложных ситуациях edmundv.home.xs4all.nl/blog/2014/01/28/…const auto&
или,const auto
если я не хочу явно изменить или переместить.auto str = std::string();
вместоstd::string str;
?Легко. Используйте его, когда вам все равно, какой тип. Например
Все, что меня волнует, это то, что
i
находится в контейнере.Это немного похоже на typedefs.
Здесь, я не забочусь ли
h
иw
являются поплавки или двойники, только то , что они независимо от типа подходит для выражения высоты и веса .Или посмотрим
Здесь все, что меня волнует, это то, что это подходящий итератор, поддерживающий
operator++()
, это похоже на типизацию утки в этом отношении.Кроме того, тип лямбда не может быть написано, так
auto f = []...
что хороший стиль. Альтернатива - приведение к,std::function
но это идет с накладными расходами.Я не могу себе представить "злоупотребление"
auto
. Самое близкое, что я могу себе представить, - это лишить себя явного преобразования в какой-то значимый тип - но вы бы не использовалиauto
для этого, вы бы создали объект нужного типа.Если вы можете удалить некоторую избыточность в своем коде, не вызывая побочных эффектов, то это должно быть хорошо.
Контрпримеры (заимствовано из чужих ответов):
Здесь нас интересует, что это за тип, поэтому мы должны написать
Someclass i;
иfor(unsigned x = y;...
источник
auto
.Действуй. Используйте
auto
везде, где это облегчает написание кода.Каждая новая функция на любом языке будет перегружена, по крайней мере, некоторыми типами программистов. Только через умеренное злоупотребление некоторыми опытными программистами (не нубами) остальные опытные программисты узнают границы правильного использования. Чрезмерное чрезмерное использование обычно плохо, но может быть хорошим, потому что такое чрезмерное использование может привести к улучшению функции или улучшению возможности ее замены.
Но если бы я работал над кодом с несколькими строками вроде
где тип указан ноль раз, я мог бы хотеть изменить эти строки, чтобы включить типы. Первый пример великолепен, так как тип указан один раз, и
auto
избавляет нас от необходимости писать беспорядочные шаблонные типы дважды. Ура для C ++++. Но явное отображение нулевого типа, если его трудно увидеть в соседней строке, заставляет меня нервничать, по крайней мере, в C ++ и его непосредственных преемниках. Для других языков, предназначенных для работы на более высоком уровне с большей абстракцией, полиморфизмом и универсальностью, это хорошо.источник
На C ++ и после 2012 года на панели « Спроси нас» состоялся фантастический обмен мнениями между Андреем Александреску, Скоттом Мейерсом и Хербом Саттером, который говорил о том, когда использовать и не использовать
auto
. Перейдите к минуте 25:03 для 4-минутного обсуждения. Все три динамика дают отличные оценки, о которых следует помнить, когда их не использоватьauto
.Я настоятельно призываю людей прийти к собственному выводу, но я забрал, чтобы использовать
auto
везде, если :Либеральное использование
explicit
помогает уменьшить беспокойство о последнем, что помогает минимизировать количество времени, в течение которого первое является проблемой.Перефразируя сказанное Хербом: «Если вы не делаете X, Y и Z, используйте
auto
. Изучите, что такое X, Y и Z, и иди и используйтеauto
везде».источник
Да, это может быть использовано в ущерб удобочитаемости. Я предлагаю использовать его в тех случаях, когда точные типы являются длинными, или невыразимыми, или не важными для читабельности, а переменные недолговечны. Например, тип итератора обычно длинный и не важен, поэтому
auto
будет работать:auto
здесь не повредит читабельности.Другим примером является тип правила синтаксического анализатора, который может быть длинным и сложным. Для сравнения:
с участием
С другой стороны, когда тип известен и прост, гораздо лучше, если он явно указан:
скорее, чем
источник
begin()
иend()
, или ваш размер шага ничего, кроме одного, или вы изменяете контейнер , как вы петли, диапазон на основе для заявления не поможет.r_and_t<r_and_t<r_char_t<char>&, r_char_t<char>&>, r_char_t<char>&>
делает?space
, и искать его. В любом случае, это более полезная информация ... в конце концов, проблема не в том, «какого типа эта новая переменная», а в том, «что этоspace & space & space
значит?». Фактический тип выражения - просто шум.auto
может быть очень опасным в сочетании с шаблонами выражений, которые часто используются библиотеками линейной алгебры, такими как Eigen или OpenCV.Ошибки, вызванные этим типом ошибок, являются основной болью для отладки. Одним из возможных способов решения этой проблемы является явное приведение результата к ожидаемому типу, если вы склонны использовать auto для стиля объявления слева направо.
источник
A*B
скопировано ли выражение вauto
переменную или что-то еще, описанное вами поведение все еще присутствует.auto
.diag(A * B)
, не нужно тратить циклы на вычисление недиагональных элементов.Я использую
auto
без ограничений и не столкнулся с какой-либо проблемой. Я даже иногда заканчиваю тем, что использую это для простых типов какint
. Это делает c ++ языком более высокого уровня для меня и позволяет объявлять переменные в c ++, как в python. После написания кода на Python я даже иногда пишу, например,вместо того
Это один из случаев, когда я бы сказал, что это злоупотребление
auto
ключевым словом.Часто я не возражаю против того, каков точный тип объекта, меня больше интересует его функциональность, и поскольку имена функций обычно говорят что-то об объектах, которые они возвращают,
auto
это не повредит: напримерauto s = mycollection.size()
, я могу догадаться, чтоs
это будет своего рода целое число, и в редком случае, когда я забочусь о точном типе, давайте проверим прототип функции (я имею в виду, что я предпочитаю проверять, когда мне нужна информация, а не априори, когда пишется код, просто в случае, если это будет полезно когда-нибудь, как вint_type s = mycollection.size()
).По поводу этого примера из принятого ответа:
В моем коде я все еще использую
auto
в этом случае, и если я хочуx
быть беззнаковым, то я использую служебную функцию с именем saymake_unsigned
, которая ясно выражает мои опасения:Отказ от ответственности: я просто описываю свое использование, я не компетентен давать советы!
источник
auto i = MyClass()
.as_unsigned
рекомендуется там, или дажеauto w = widget{};
.Одна из основных проблем с программой на C ++ - она позволяет использовать неинициализированную переменную . Это приводит нас к неприятному недетерминированному поведению программы. Следует отметить, что современный компилятор теперь выдает соответствующие предупреждающие сообщения / сообщения, если программа устает его использовать.
Чтобы проиллюстрировать это, рассмотрим ниже программу на С ++:
Если я скомпилирую эту программу, используя современный компилятор (GCC), она выдаст предупреждение. Такое предупреждение может быть неочевидным, если мы работаем с действительно сложным рабочим кодом.
================================================== =============================== Теперь, если мы изменим нашу программу, которая использует auto , то после компиляции мы получим следующее:
При использовании auto невозможно использовать неинициализированную переменную. Это главное преимущество, которое мы можем получить (бесплатно), если начнем использовать auto .
Эту концепцию и другую великолепную современную концепцию C ++ объясняет эксперт C ++ Херб Шуттер в своем выступлении на CppCon14 :
Вернуться к основам! Основы современного стиля C ++
источник
auto
.auto
- но вам это не нужно, чтобы избежать этой проблемы.Одна опасность, которую я отметил, заключается в ссылках. например
Проблема в том, что another_ref на самом деле не является ссылкой в этом случае, это MyBigObject вместо MyBigObject &. В итоге вы копируете большой объект, не осознавая этого.
Если вы получаете ссылку непосредственно из метода, вы можете не думать о том, что это на самом деле.
вам понадобится "auto &" или "const auto &"
источник
Используйте
auto
там, где имеет смысл выводить тип. Если у вас есть что-то, что, как вы знаете, является целым числом, или вы знаете, что это строка, просто используйте int / std :: string и т. Д. Я бы не стал беспокоиться о «чрезмерном использовании» языковой функции, если она не дошла до абсурда, или запутывает код.Это мое мнение в любом случае.
источник
auto
Ключевое слово может использоваться только для локальной переменной, но не для аргументов или членов класса / структуры. Таким образом, это безопасно и целесообразно использовать их где угодно. Я часто их использую. Тип выводится во время компиляции, отладчик показывает тип во время отладки,sizeof
сообщает об этом правильно,decltype
дает правильный тип - вреда нет. Я не считаюauto
чрезмерным, никогда!источник
TL; DR: см. Практическое правило внизу.
Общепринятый ответ предлагает следующее правило:
Но я бы сказал, что это слишком ограничительно. Иногда меня не интересуют типы, так как утверждение достаточно информативно, и я не удосужился потратить время на выяснение типа. Что я имею в виду под этим? Рассмотрим пример, который появился в некоторых ответах:
Что делает это примером неправильного использования
auto
? Это мое невежество оf()
типе возврата? Ну, это может действительно помочь, если бы я знал это, но - это не моя главная забота. Гораздо более серьезной проблемой является то , чтоx
иf()
довольно бессмысленно. Если бы мы имели:вместо этого мне обычно все равно, очевиден ли возвращаемый тип функции или нет. Читая утверждение, я знаю, что делаю, и знаю достаточно о том, что такое семантика возвращаемого значения, чтобы не чувствовать, что мне нужно также знать его тип.
Итак, мой ответ: используйте
auto
всякий раз, когда это позволяет компилятор, если только:А также:
auto
на конкретный тип.источник
Один мой горький опыт с
auto
как использовать его с лямбда - выражений :Собственно, здесь
i
разрешено указатель на функциюint(*)()
. Это простоcout
, но только представьте, какие плохие ошибки компиляции / выполнения могут возникнуть при использовании сtemplate
.Вы должны избегать
auto
с такими выражениями и поставить правильныйreturn
тип (или контролируемыйdecltype()
)Правильное использование для приведенного выше примера будет,
источник
()
в конце. Лямбды должны действовать как функции, и отсюда происходит преобразование указателя на функцию. Если вы хотите позвонить прямо сейчас, зачем вообще использовать лямбду?auto i = 0;
работает довольно хорошо.auto x = []() { /* .... whatever goes in here ... */ }()
лучше, чемauto x = /* .... whatever goes in here ... */;
то же самое, без лямбды? Я считаю, что это довольно бессмысленно, по той же причинеauto x = 42 + y - 42
бессмысленно.