Разница между const auto & и объектом auto & if является const
// case 1
const int i = 42;
const auto &k = i;
// case 2
const int i = 42;
auto &k = i;
Нужно ли нам ключевое слово const
перед auto
в этом сценарии? В конце концов, ссылка (k
) на автовыводимый тип будет включать в себя верхний уровень const
объекта ( const
int i
). Поэтому я считаю, что k
будет ссылкой на целое число, которое является константным (const int &k
) в обоих случаях.
Если это правда, означает ли это, что const auto &k = i;
в случае, когда 1 заменяется компилятором как const int &k = i;
(auto
заменяется на int
)? Если в случае 2 auto
заменяется на const int
?
Ответы
Ответ 1
auto
ключевое слово автоматически определяет тип переменной во время компиляции.
В вашем первом случае auto
сведен к int
где он сокращается до const int
во втором случае. Таким образом, оба ваших случая сводятся к одному и тому же коду:
const int &k = i;
Тем не менее, лучше иметь сопзЬ явно для лучшей читаемости и чтобы убедиться, что ваша переменная ДЕЙСТВИТЕЛЬНО является const
.
Ответ 2
Вывод типа с auto
такими как вывод типа аргумента шаблона с несколькими исключениями, которые не применяются в данном примере. следовательно
const int i = 42;
const auto& k1 = i; // same as const int& k1 = i;
auto& k2 = i; // same as (const int)& k2 = i;
Вероятно, более читаемо добавить квалификатор const
.
Вот еще один пример, в котором поддержка краткости с auto
вводит в заблуждение:
int *i;
const auto k1 = i; // same as int* const k1 = i;
const auto *k2 = i; // same as const int *k2 = i;
В первом случае объект, на который i
указываю, может быть изменен через k1
, во втором случае он не может.
Ответ 3
Принятый ответ правильный, т.е. Нет никакой разницы в отношении скомпилированного результата. Что важно отметить, что auto&
версия сопряжения const
-ness в k
ссылки с const
-ness переменной i
. Я понял, что, поскольку вопрос называется "Разница между const auto & auto &...", тогда важно подчеркнуть прагматическую разницу здесь, в которой, если вы не ставите ключевое слово const
, вы не можете гарантировать, что ссылка будет иметь это cv-квалификация. В некоторых случаях, когда это желательно, зачем оставлять его на волю случая, что i
будет оставаться const
в будущем?
Ответ 4
Привет и приветствуем переполнение стека.
Как показывает эта небольшая тестовая программа, независимо от того, как вы указываете тип k
, компилятор никогда не позволит вам потерять константу i
.
#include <iostream>
#include <type_traits>
#include <string>
#define XSTR(s) STR(s)
#define STR(s) #s
template<class T>
struct type;
template<>
struct type<int>
{
static std::string name() { return "int"; }
};
template<class T>
struct type<T&&>
{
static std::string name() { return type<T>::name() + " &&"; }
};
template<class T>
struct type<T&>
{
static std::string name() { return type<T>::name() + " &"; }
};
template<class T>
struct type<T const>
{
static std::string name() { return type<T>::name() + " const"; }
};
#define REPORT_CONST(decl, var, assign) \
{ \
decl var = assign; \
do_it(STR(decl var = assign;), var); \
}
template<class Var>
void do_it(const char* message, Var&&)
{
std::cout << "case: " << message << " results in type: " << type<Var>::name() << '\n';
}
int main()
{
const int i = 42;
REPORT_CONST(const auto &, k, i);
REPORT_CONST(auto &, k, i);
REPORT_CONST(auto &&, k, std::move(i));
REPORT_CONST(auto const &&, k, std::move(i));
REPORT_CONST(int const&, k, i);
// REPORT_CONST(int &, k, i); // error: binding reference of type 'int&' to 'const int' discards qualifiers
}
Ожидаемые результаты:
case: const auto & k = i; results in type: int const &
case: auto & k = i; results in type: int const &
case: auto && k = std::move(i); results in type: int const &
case: auto const && k = std::move(i); results in type: int const &
case: int const& k = i; results in type: int const &
http://coliru.stacked-crooked.com/a/7c72c8ebcf42c351
Обратите внимание также на распад названных значений r на l-значения.
Ответ 5
Существует небольшая разница в первом случае auto
будет выведено на const int
а во втором случае - на int
(поскольку вы экспрессивно указали const).
cpp-опорные состояния
Ключевое слово auto может сопровождаться модификаторами, такими как const или &, которые будут участвовать в выводе типа. Например, при условии const auto & я = expr; тип я является именно типом аргумента u в мнимом шаблоне шаблона void f (const U & u), если компиляция функции f (expr) была скомпилирована. Следовательно, auto && может быть выведено либо в качестве ссылки на lvalue, либо в качестве значения rvalue в соответствии с инициализатором, который используется в цикле для диапазона.
Поэтому для вас это означает
// case 1
const int i = 42;
const auto &k = i; // auto -> int
// case 2
const int i = 42;
auto &k = i; // auto -> const int
Однако более важным, на мой взгляд, является то, что намерение сформулировано более четко, если вы утверждаете const inccitly и гарантируете постоянство. Поэтому в этом случае я бы предпочел это.