Почему `const T &` не обязательно будет const?

template<typename T>
void f(T a, const T& b)
{
    ++a; // ok
    ++b; // also ok!
}

template<typename T>
void g(T n)
{
    f<T>(n, n);
}

int main()
{
    int n{};
    g<int&>(n);
}

Обратите внимание: b имеет значение const T&, а ++b в порядке!

Почему const T& не обязательно является константой?

57
задан 20 March 2019 в 16:41

2 ответа

Добро пожаловать в константу и ссылка, выходящая из строя . Когда Вы имеете const T&, к ссылке относятся T и const - также. Вы звоните g как [1 126]

g<int&>(n);

, таким образом, Вы указали, что T int&. Когда мы применяем ссылку на lvalue ссылку, эти два ссылочных коллапса к единственному, таким образом int& & становится всего int&. Затем мы добираемся до правила от [1 125] [dcl.ref]/1, который указывает, что, если Вы подаете заявку const к ссылке, она отбрасывается, таким образом int& const просто становится int& (обратите внимание, что Вы не можете на самом деле объявить int& const, она должна прибыть из определения типа или шаблона). Это означает для [1 127]

g<int&>(n);

, Вы на самом деле звоните

void f(int& a, int& b)

, и Вы на самом деле не изменяете константу.

<час>

Имел Вас, звонил g, как

g<int>(n);
// or just
g(n);

затем T будет int, и f искоренялся бы как [1 131]

void f(int a, const int& b)

, Так как T больше не ссылка, const и эти & относятся это, и Вы получили бы ошибку компилятора для попытки изменить постоянную переменную.

64
ответ дан 1 November 2019 в 17:14

Я знаю, что уже существует принятый ответ, который корректен, но только добавить к нему немного, даже вне области шаблонов и только в объявлениях функции в целом...

( const T& ) 

не то же как

( const T )

В Вашем примере, который соответствует первому, у Вас есть ссылка константы. Если Вы действительно хотите значение константы, которое не является модифицируемым, удаляют ссылку как во втором примере.

-3
ответ дан 1 November 2019 в 17:14

Другие вопросы по тегам:

Похожие вопросы: