2016-05-13 2 views
3

Я замечаю нечетную семантику, ссылаясь на ссылки на указатели и массивы, которые различаются по консистенции элементов с указателем и массивом соответственно. С указателями это не удается предсказуемо:Binding const T (& ref) [N] к объекту типа T [N]

int* p{}; 
const int*& p_ref{p}; 

non-const lvalue reference to type 'const int *' cannot bind to a value of unrelated type 'int *' 

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

Однако то, что я думал, что должно быть аналогично с массивами не

int arr[5]{}; 
const int (&arr_ref)[5]{arr}; 

лязг и НКУ как компилировать выше без жалоб, но почему? Я связываю неконстантную ссылку на const int[5] на объект типа int[5]. Почему это разрешено?

Update: Аналогичная проблема описывается Gotcha # 32 (стр 82) в C++ Gotchas Стивене С. Dewhurst

+0

Также рассмотрим 'int * const & p_ref {p};'. – Hurkyl

+0

@Hurkyl Это просто нормальное связывание const ref с переменной non const? –

+0

Континентальное размещение констант здесь имеет значение: https://kuhllib.com/2012/01/17/continental-const-placement/ – Arvid

ответ

7

С первым примером, если это было разрешено, то можно было бы нарушить константную правильность ,

int *p{}; 
const int*& p_ref{p}; // pretend this is okay 
const int x = 10; 
p_ref = &x;   // storing the address of a const int in a const int*, okay 
*p = 5;    // Should be okay, because p is int*, not const int*, 
         // but oops, just modified a const value 

Ссылка на массив не имеет этой проблемы, потому что вы не можете указать массив где-то еще (так как это не указатель).

Существует аналогичная проблема с указателями на указатели. Часто бывает, что мы храним адрес неконстантного T в const T*. Поскольку это нормально, люди склонны думать, что должно быть возможно сохранить адрес T* в const T**. Но это приводит к той же проблеме, что и в приведенном выше примере:

int* p; 
const int** pp = &p; // forbidden, but pretend it's okay for now 
const int x = 10; 
*pp = &x;    // storing the address of a const int in a const int*, okay 
*p = 5;    // oops, modified a const int 
Смежные вопросы