Разница между const auto & и auto & если объектом ссылки является 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?

5 ответов


auto сайта автоматически определяет тип переменной во время компиляции.

в первом случае auto снижена до int где это сводится к const int во втором случае. Таким образом, оба ваших случая сводятся к тому же коду, что и:

const int &k = i;

однако лучше иметь const явно для лучшей читаемости и убедиться, что ваша переменная истинно и const.


тип вычета с 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, во втором случае это невозможно.


привет и добро пожаловать в Stack overflow.

как показывает эта небольшая тестовая программа, независимо от того, как вы указываете тип 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-значения.


принятый ответ правильный, т. е. нет никакой разницы в отношении к составлен результат. Важно отметить, что на auto& версия соединение the const-ность k С const - ness переменной i. Я понял, так как вопрос называется'разница между const auto & и auto & ...' тогда важно подчеркнуть прагматическое различие здесь, в котором, если вы не ставите the const ключевое слово, вы не можете гарантировать, что ссылка будет иметь это cv-квалификация. В некоторых сценариях, где это желательно,почему оставить это на волю случая, что i останется const в будущем?


есть небольшая разница в первом случае auto будет выведено const int а во втором случае до int (как вы explcitly заявил константный).

cpp-ссылочные состояния

ключевое слово auto может сопровождаться модификаторами, такими как const или&, которые будут участвовать в дедукции типа. Например, учитывая const auto& i = expr;, тип i является именно типом аргумента u в воображаемом шаблоне шаблона void f (const U& u), если был скомпилирован вызов функции f(expr). Поэтому auto&& может быть выведена либо как ссылка lvalue, либо как ссылка rvalue в соответствии с инициализатором, который используется в цикле for на основе диапазона.

так что для вас это значит

// 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 explcitly и гарантирует постоянство. Поэтому в данном случае я бы предпочел он.