将const T(&ref)[N]绑定到类型为T [N]的对象

Rya*_*ing 3 c++ arrays pointers reference c++11

我注意到奇怪的语义wrt绑定对指针和数组的引用,这些指针和数组分别在指向和数组元素的常量上有所不同.使用指针,这可以预测失败:

int* p{};
const int*& p_ref{p};
Run Code Online (Sandbox Code Playgroud)

non-const lvalue reference to type 'const int *' cannot bind to a  value of unrelated type 'int *'
Run Code Online (Sandbox Code Playgroud)

有道理,指向int和指针指向const-int是两种不同的类型,const&允许编译器生成临时之前添加一个,这有效,但不会改变上述内容.

但是,我认为应该与数组类似的不是

int arr[5]{};
const int (&arr_ref)[5]{arr};
Run Code Online (Sandbox Code Playgroud)

clang和gcc都在没有抱怨的情况下编译上面的内容,但为什么呢?我将非const引用绑定const int[5]到类型的对象int[5].为什么允许这样做?

更新: Stephen C. Dewhurst 在C++ Gotchas中描述了类似的问题#32(第82页)

Ben*_*ley 7

使用您的第一个示例,如果允许,则可能会破坏const正确性.

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
Run Code Online (Sandbox Code Playgroud)

对数组的引用没有这个问题,因为你不能将数组指向其他地方(因为它不是指针).

指针指针有类似的问题.通常情况下,我们将非const的地址存储T在a中const T*.因为这是可以的,人们倾向于认为应该可以存储a 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
Run Code Online (Sandbox Code Playgroud)