我注意到奇怪的语义wrt绑定对指针和数组的引用,这些引用和数组分别在指向和数组元素的常量中不同。使用指针,这可以预测失败:
int* p{};
const int*& p_ref{p};
non-const lvalue reference to type 'const int *' cannot bind to a value of unrelated type 'int *'
有道理,指向int的指针和指向const-int的指针是两种不同的类型,在const
允许编译器生成临时代码之前添加&
,但是有效,但是不会改变上述情况。
然而,我认为应该与数组类似的不是
int arr[5]{};
const int (&arr_ref)[5]{arr};
clang和gcc都在没有抱怨的情况下编译上面的内容,但为什么呢?我将const int[5]
的非const引用绑定到类型为int[5]
的对象。为什么允许这样做?
更新:由Stephen C. Dewhurst撰写的C++ Gotchas中的问题#32(第82页)描述了类似的问题
答案 0 :(得分: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
对数组的引用没有这个问题,因为你不能将数组指向其他地方(因为它不是指针)。
指针指针存在类似的问题。通常情况下,我们将非const 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