Разница между const auto & и auto &, если объект ссылки постоянный - PullRequest
0 голосов
/ 06 сентября 2018
// 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 ]

0 голосов
/ 06 сентября 2018

Привет и добро пожаловать в стек переполнения.

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

Обратите внимание также на уменьшение именованных r-значений до l-значений.

0 голосов
/ 06 сентября 2018

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

0 голосов
/ 06 сентября 2018
Ключевое слово

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

В первом случае auto уменьшается до int, а во втором случае уменьшается до const int. Итак, оба ваших дела сводятся к одному и тому же коду:

const int &k = i;

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

0 голосов
/ 06 сентября 2018

Вывод типа с помощью 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, во втором случае он не может.

0 голосов
/ 06 сентября 2018

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

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

...