Почему нет неявного преобразования из указателя в ссылку? - PullRequest
1 голос
/ 20 мая 2019
#include <iostream>
using namespace std;

int main() {
    int x = 5;
    int* y = &x;
    int& z = y;
    return 0;
}

Для этого кода компилятор выдает ошибку на int& z = y;, говоря:

./example.cpp: In function 'int main()':

./example.cpp:7:11: error: invalid conversion from 'int*' to 'int' [-fpermissive]

    7 |  int& z = y;

      |           ^

      |           |

      |           int*

./example.cpp:7:11: error: cannot bind rvalue '(int)y' to 'int&'

Почему?Я знаю, почему ошибка, и я знаю, как ее исправить, мне любопытно, почему компилятор не может неявно выполнить преобразование, когда мне кажется тривиальным мое намерение сделать указатель и ссылку ссылающимися ната же ячейка памятиЕсть ли какие-нибудь дела, в которых я скучаю?

Ответы [ 3 ]

5 голосов
/ 20 мая 2019

C ++ имеет долгую историю ошибок, связанных с неявными преобразованиями.Взгляните на книгу Стивена Дьюхерста "C ++ Gotchas";Самая длинная глава посвящена обращениям.Эта тема буквально полна ловушек, и мы должны быть рады, что вышеприведенное должно быть напечатано явно.При этом ...

Есть ли какие-то угловые случаи, которые мне не хватает?

Рассмотрим такой набор перегрузки:

void f(void *n);
void f(int& n);

иизображения, которые указатели неявно конвертировать в ссылки.Следующий вызов

int n = 42;

f(&n);

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

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

int n = 42;
int* ptr = &n;

int*& refToPtr = ptr;

С неявным указателем на преобразование ссылок вышеприведенное будет компилироваться и для

int& refToPtr = &n;

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

1 голос
/ 20 мая 2019

Указатель может быть нулевым, ссылка не может.

Примечание: вы не можете сделать это

int* ptr = nullptr;
int& ref = *ptr; // dereferencing a nullptr is UB

Если C ++ разрешает имплицитное преобразование для ссылки на указатель, это означает, что он будет косвенно задерживать указатель, который может быть UB.

1 голос
/ 20 мая 2019

Вы должны рассматривать ссылку на C ++ как псевдоним, а не указатель. Это отличается от ссылок на Java, которые больше похожи на указатель. Тогда сообщение компилятора будет совершенно ясным: объект с псевдонимом должен быть int, и вы пытаетесь ссылаться на int *.

Для получения дополнительной информации о ссылках: https://isocpp.org/wiki/faq/references

...