对“const int *”类型的非 const 左值引用不能绑定到不相关类型“int *”的值

Posted

技术标签:

【中文标题】对“const int *”类型的非 const 左值引用不能绑定到不相关类型“int *”的值【英文标题】:non-const lvalue reference to type 'const int *' cannot bind to a value of unrelated type 'int * 【发布时间】:2020-04-24 16:19:17 【问题描述】:
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,我不是说ji 的引用并且我们不允许修改i 指向的intj 吗?

【问题讨论】:

但我不是 const... @MrBens 我知道,但这有关系吗? 好吧,当你写const int * &j时,你应该给它分配一个const int *。这真的取决于你在这里想要达到的目标。 嗯,但是如果您放弃引用,您可以将 const int * 分配给 int * 没有问题,对吧?如果是这样,为什么引用会改变事情? 出于与const ptr ptr conversion 相同的原因,尽管使用的是引用而不是指针。简单的修复是const int * const&j = i; 【参考方案1】:

所以如果我设置它等于 i,我不是说 j 是 i 的引用

这就是你想说的。但是i的类型不兼容,所以不能说。

而且我们不允许通过j修改i指向的int?

如果你有一个指向 const 的指针,那么你就不能修改指向的 int。您可以使用j 引用此类指针。但是你还没有创建这样的指针。

然而,指向非 const 的指针可以转换为指向 const 的指针。但是这种转换的结果是一个右值,所以你对非常量的引用不能绑定到它。如果您使用对 const 的引用,它将延长隐式转换的临时结果的生命周期:

const int * const &j = i;

但引用只是增加了不必要的混乱。最好给转换后的指针命名,而不是引用临时对象:

const int* j = i;

为什么i的类型不兼容?

因为语言规则是这样说的。

这只是规则吗?

这是规则(来自最新的标准草案):

给定类型“cv1 T1”和“cv2 T2”,如果 T1 与 T2 相似 ([conv.qual]),或者 T1 是 T2 的基类,则“cv1 T1”与“cv2 T2”引用相关. 如果“指向 cv2 T2 的指针”类型的纯右值可以通过标准转换序列 ([conv]) 转换为“指向 cv1 T1 的指针”类型,则“cv1 T1”与“cv2 T2”引用兼容。 在使用两种类型的引用兼容关系来确定引用绑定的有效性并且标准转换序列格式错误的所有情况下,需要这种绑定的程序是格式错误的。

对“cv1 T1”类型的引用由“cv2 T2”类型的表达式初始化,如下所示:

如果引用是左值引用和初始化表达式

是一个左值(但不是位域),并且“cv1 T1”与“cv2 T2”是引用兼容的,或者

具有类类型(即 T2 是类类型),其中 T1 与 T2 没有引用相关,并且可以转换为“cv3 T3”类型的左值,其中“cv1 T1”是与“cv3 T3”92 的引用兼容(通过枚举适用的转换函数([over.match.ref])并通过重载决议选择最佳转换函数来选择此转换),

那么引用在第一种情况下绑定到初始化表达式左值,在第二种情况下绑定到转换的左值结果(或者,在任何一种情况下,都绑定到对象的适当基类子对象)。

否则,如果引用是对非 const 限定或 volatile 限定类型的左值引用,则程序是不正确的。

【讨论】:

啊。我正试图解决这个问题。为什么i的类型不兼容?这只是规则吗? @user5965026 因为const int*int* 不是同一类型。当*** cv 限定符被忽略时,它们甚至不是同一类型(两者都是非常量)。它们在继承层次结构中也不相关。 啊,我想我刚刚意识到这种情况类似于尝试设置对 r 值的非常量引用。我没有认识到的是,由于 int *const int * 的隐式转换,当前情况下的 RHS 不是左值而是右值。是这个主意吗?此外,当您将额外的const 放入其中时,const int * const &j = i; 类似于const int &j = some_r_value 并且是有效的,但int &j = some_r_value 并不是因为some_r_value 是临时的 @user5965026 是的。 i 本身就是一个左值。但不是由于类型错误而可以将引用绑定到的左值。如果引用不是非常量,则引用可以绑定到隐式转换的结果,因为该隐式转换的结果是右值,即与该示例的原因相同。

以上是关于对“const int *”类型的非 const 左值引用不能绑定到不相关类型“int *”的值的主要内容,如果未能解决你的问题,请参考以下文章

是否有理由我们能够在类定义中定义 [static const int] 而不能在其他静态 const 类型中定义? [复制]

c语言里const int 和int 有啥区别,const的作用是啥。

初始化数据表sequence(const int&,const int&,float)括号里什么意思?

从 double 到 const int 的 C++ 类型转换无法正常工作

对loadimage(IMAGE *,char const *,int,int,bool)的未定义引用

int *p,cons int *p,int const *p,int * const p,const int * const p,int const * const p的差别