2015-04-25 7 views
19

При создании локальных переменных правильно ли использовать (const) auto& или auto?C++ auto & vs auto

.: например

SomeClass object; 
const auto result = object.SomeMethod(); 

const auto& result = object.SomeMethod(); или

Где SomeMethod() возвращает не элементарное значение - может быть другой определенный пользователем тип. Я понимаю, что const auto& result верен, так как результат, возвращаемый SomeMethod(), вызовет конструктор копирования для возвращаемого типа. Пожалуйста, поправьте меня, если я ошибаюсь.

Что относительно примитивных типов? Я предполагаю, что const auto sum = 1 + 2; верен.

Это относится также к диапазону, основанному на циклах?

for(const auto& object : objects) 
+1

Я настоятельно рекомендую вам прочитать следующее: https://www.safaribooksonline.com/library/view/effective-modern-c/9781491908419/ch01.html Первые две главы являются бесплатными и описывают вывод типа шаблона, который по существу как работает 'auto' (за исключением специфического случая' initializer_list', которые не выведены в контексте шаблона), затем выведите 'aut' тип вывода. – vsoftco

ответ

12

Да, это правильно использовать auto и auto& для локальных переменных. При получении возвращаемого типа функции также правильно использовать auto&. Это относится и к диапазону, основанному на циклах.

Общие правила использования auto являются:

  • Выберите auto x, если вы хотите работать с копиями.
  • Выберите auto &x, если вы хотите работать с оригинальными элементами и можете их изменить.
  • Выберите auto const &x, если вы хотите работать с оригинальными элементами и будете не изменять их.

Узнать больше об этом авто уточнении here.

3

auto использует тот же механизм типа дедукции в качестве шаблонов, единственное исключение, которое я отдаю себе отчет в том, что из-скрепляющих инициализации списков, которые выводятся на auto в std::initializer_list, но не выводится в контексте шаблона.

auto x = expression; 

работы первой зачистка всех опорные и резюме отборочных от типа правой стороны выражения, то соответствующий типа. Например, если у вас есть const int& f(){...}, то auto x = f(); выдает x как int, а неconst int&.

Другая форма,

auto& x = expression 

не удаляет в CV-классификаторов, поэтому, используя пример выше, auto& x = f() дедуцирует x, как const int&. Другие комбинации просто добавляют cv отборочные.

Если вы хотите, чтобы ваш тип всегда выводился с помощью квалификаторов cv-ref, используйте пресловутый decltype(auto) в C++ 14, в котором используются правила вычитания типа decltype.

Итак, если вы хотите копировать, используйте auto, если вы хотите использовать ссылки, используйте auto&. Используйте const всякий раз, когда вы хотите дополнительно const -ness.


EDIT Существует дополнительный случай использования,

auto&& x = expression; 

который использует эталонные сворачивания правила, такие же, как и в случае ссылок экспедиторских в коде шаблона. Если expression является lvalue, то x является ссылкой на lvalue с cv-квалификаторами expression. Если expression является rvalue, то x является ссылкой rvalue.

+0

@Potatoswatter Спасибо, отредактирован. Я действительно задаюсь вопросом о cv для 'rvalues'. Есть ли простой способ тестирования? И как вы можете получить квалификацию cv? При возврате функции cv отбрасывается. – vsoftco

+0

Нет, он не отбрасывается при возврате функции.Он отбрасывается для prvalues ​​всех скалярных типов (C++ 14 [и других выпусков] § 5/6). Вы можете получить его с помощью вызова функции или нотации. Cv-квалифицированные xvalues ​​работают так же, как и все остальное: 'auto && x = std :: move < const int > (5);' будет объявлять 'int const && x', хотя они редко используются. – Potatoswatter

+0

@Potatoswatter благодарит вас, вы правы, моя ошибка. Сначала я тестировал POD, и в этом случае cv отбрасывается, и считается, что это общий случай. Разумеется, его нельзя отбрасывать, так как в общем случае можно сохранить cv (например, невозможно вызвать функцию non-const member при возврате rvalue). – vsoftco

30

auto и auto && крышка большинстве случаев:

  • Использование auto когда требуется локальная копия. Это никогда не даст ссылки. Конструктор копирования (или перемещения) должен существовать, но он не может быть вызван, из-за оптимизации elision.

  • Используйте auto &&, если вам все равно, является ли объект локальным или нет. Технически это всегда будет давать ссылку, но если инициализатор является временным (например, функция возвращает значение), он будет вести себя как ваш собственный локальный объект.

    Кроме того, auto && не гарантирует, что объект может быть изменен. Учитывая объект или ссылку const, он выведет const. Однако модифицируемость часто принимается с учетом конкретного контекста.

auto & и auto const & немного более конкретно:

  • auto & гарантирует, что вы разделяете переменную с чем-то другим. Это всегда ссылка и никогда не временная.

  • auto const & как auto &&, но обеспечивает доступ только для чтения.

насчет для примитивных/непримитивных типов?

Нет никакой разницы.

Это относится также к диапазону, основанному на циклах?

Да. Применяя вышеуказанные принципы,

  • Использовать auto && для возможности изменять и отбрасывать значения последовательности в цикле.(То есть, если контейнер не предоставляет представление только для чтения, такое как std::initializer_list, и в этом случае оно будет эффективно auto const &.)
  • Используйте auto &, чтобы изменить значения последовательности значимым образом.
  • Используйте auto const & для доступа только для чтения.
  • Используйте auto для работы с (изменяемыми) копиями.

Вы также указываете auto const без ссылки. Это работает, но это не очень часто используется, поскольку редко доступ к доступу только для чтения к тому, что у вас уже есть.

0

При создании локальных переменных, правильно ли использовать (const) auto & или auto?

Да. Авто - это не что иное, как тип, основанный на компиляторе, поэтому используйте ссылки, в которых вы обычно используете ссылки, и локальные (автоматические) копии, где вы обычно используете локальные копии. Независимо от того, использовать ссылку или нет, не зависит от вычитания типа.

Где SomeMethod() возвращает не-примитивное значение - возможно, другой пользовательский тип. Я понимаю, что const auto & результат верен, так как результат, возвращаемый SomeMethod(), вызовет конструктор копирования для возвращаемого типа. Пожалуйста, поправьте меня, если я ошибаюсь.

Юридический? Да, с константой. Лучшая практика? Наверное, нет, нет. По крайней мере, не с C++ 11. Особенно нет, если значение, возвращаемое из SomeMethod(), уже является временным. Вы хотите узнать о C++ 11 перемещение семантику, копировать Пропуска и вернуть значение оптимизации: https://juanchopanzacpp.wordpress.com/2014/05/11/want-speed-dont-always-pass-by-value/

http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=199

https://isocpp.org/wiki/faq/ctors#return-by-value-optimization

насчет для примитивных типов? Я предполагаю const auto sum = 1 + 2; верно.

Да, это нормально.

Это относится также к диапазону, основанному на циклах?

для (сопзЬ авто & объекта: объекты)

Да, это тоже хорошо. Я все время пишу такой код.