Подтвердить что ты не робот

С++ auto & vs auto

При создании локальных переменных правильно ли использовать (const) auto& или 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)
4b9b3361

Ответ 1

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

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

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

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

auto & и auto const & являются более конкретными:

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

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

Как насчет примитивных/не-примитивных типов?

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

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

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

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

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

Ответ 2

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

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

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

Вы можете узнать больше об автоспециалисте здесь.

Ответ 3

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

auto x = expression;

работает, сначала удаляя все ссылочные и cv-квалификаторы из типа выражения правой стороны, а затем сопоставляя тип. Например, если у вас 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) в С++ 14, который использует правила вывода типа decltype.

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


ИЗМЕНИТЬ Существует дополнительный вариант использования,

auto&& x = expression;

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

Ответ 4

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

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

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

Юридический? Да, с константой. Лучшая практика? Наверное, нет, нет. По крайней мере, не с С++ 11. Особенно нет, если значение, возвращаемое из SomeMethod(), уже является временным. Вы захотите узнать о семантике перемещения С++ 11, скопировать elision и оптимизацию возвращаемого значения: 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; правильно.

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

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

для объекта (const auto & object: objects)

Да, это тоже нормально. Я все время пишу этот код при работе.