неконстантная ссылка lvalue на тип 'const int *' не может связываться со значением несвязанного типа 'int * - PullRequest
0 голосов
/ 24 апреля 2020
int main(int argc, char const *argv[])
{    
   int *i;
   const int * &j = i;
}

Этот код выдает ошибку error: non-const lvalue reference to type 'const int *' cannot bind to a value of unrelated type 'int *

Но мне не понятно, почему это не разрешено. Я определил j как ссылку на указатель на константу int. Поэтому, если я установлю его равным i, разве я не говорю, что j является ссылкой на i, и мы не можем изменять int, на который указывают i до j?

1 Ответ

0 голосов
/ 24 апреля 2020

Итак, если я установлю его равным i, разве я не говорю, что j является ссылкой на i

Это то, что вы пытаетесь сказать. Но тип i несовместим, так что это нельзя сказать.

, и мы не можем изменять int, на который указывает i, через j?

Если у вас был указатель на const, вы не могли бы изменить указанный int. И вы можете ссылаться на такой указатель с помощью j. Но вы не создали такой указатель.

Однако указатель на неконстантный может быть преобразован в указатель на константный. Но результатом такого преобразования является значение, поэтому ваша ссылка на non-const не может быть привязана к нему. Если вы использовали ссылку на const, это продлило бы время жизни временного результата неявного преобразования:

const int * const &j = i;

Но ссылка просто добавляет ненужное слияние. Лучше дать преобразованному указателю имя, а не ссылаться на временный объект:

const int* j = i;

Почему тип i несовместим?

Потому что правила языка говорят так.

Это только правило?

Это правило (из последней версии стандарта):

Для заданных типов «cv1 T1» и «cv2 T2» «cv1 T1» связан со ссылкой на «cv2 T2», если T1 похож ([conv.qual]) на T2, или T1 является базовым классом T2. «Cv1 T1» совместим со ссылками с «cv2 T2», если значение типа «указатель на cv2 T2» можно преобразовать в тип «указатель на cv1 T1» через стандартную последовательность преобразования ([conv]). Во всех случаях, когда эталонно-совместимые отношения двух типов используются для установления sh достоверности эталонной привязки и стандартной последовательности преобразования, будут неверно сформированы, программа, которая требует такой привязки, неверно сформирована.

Ссылка на тип «cv1 T1» инициализируется выражением типа «cv2 T2» следующим образом:

  • Если ссылка является ссылкой lvalue и выражением инициализатора

    • является lvalue (но не битовым полем), а «cv1 T1» является эталонно-совместимым с «cv2 T2», или

    • имеет тип класса (т. Е. T2 является типом класса), где T1 не связан со ссылкой на T2 и может быть преобразован в lvalue типа «cv3 T3», где «cv1 T1» совместим со ссылками с «Cv3 T3» 92 (это преобразование выбирается путем перечисления применимых функций преобразования ([over.match.ref]) и выбора наилучшего с помощью разрешения перегрузки),

затем ссылка привязывается к выражению инициализатора lvalue в первом случае и к результату lvalue преобразования во втором случае (или, в любом случае, к соответствующему подобъекту базового класса объекта).

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