为什么const char * const&=“ hello”可以编译?

时间:2018-08-27 04:39:39

标签: c++ reference const language-lawyer

我正在从一本书中阅读代码片段,并找到了它:

const char* const & a = "hello"; //can compile 
const char*& a = "hello"; //cannot

我所知道的是,初始化引用时,指向指针转换的数组不会发生。

const char* const &,对const pointer的引用,指针指向const char

const char*&,对pointer的引用,指针指向 const char

那么为什么要添加一个额外的const来指示指针是const呢?

2 个答案:

答案 0 :(得分:37)

它本质上是遵循这个公式

T const & a = something_convertible_to_T;

其中T是const char*。在第一种情况下,可以实现一个临时指针,为其分配文字的地址,然后将其自身绑定到该引用。在第二种情况下,由于左值引用不是const,因此不会发生。另一个例子更多

const char* && a = "hello"; // rvalue ref makes a no into a yes.

现在,临时指针已绑定到右值引用。

答案 1 :(得分:8)

在阅读了@StoryTeller的出色回答之后,一些无聊的措辞也变得无聊了,因为我不得不对此进行另外的思考。

因此,在语法上,我们两行都定义了 reference a,并且在这两行中,我们都将有一个materialization of a temporary pointer,它使用 string文字的地址< / em>。 两者之间的唯一区别是第二个const仅出现在此处:

const char* const & a = "hello";

而不是这里:

const char*& a = "hello";

第二个const表示此处引用的对象 a pointer in this case, is itself const,因为无法使用此引用对其进行修改。

因此,因为此字符串文字 type const char[6](例如,不是const char *),所以我们的lvalue第二行中对类型const char*的引用不能绑定到它-但第一行中对类型const char* const的引用可以。为什么?由于rules of reference initialization

  

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

     
      
  • (5.1)如果引用是左值引用和初始值设定项表达式

         
        
    • (5.1.1)是左值(但不是位字段),并且“ cv1 T1”与“ cv2 T2”具有参考兼容性,[...]
    •   
    • (5.1.2)具有类类型(即T2是类类型)[...]
    •   
  •   

两个表达式都是 lvalue ,但是我们的“ cv1 T1”不是reference-compatible ,而我们的“ cv2 T2”和“ T2”不是类类型。

  
      
  • (5.2)否则,如果引用是对非const限定类型或volatile限定类型的左值引用,则程序格式错误
  •   

引用确实是不是 const限定的:我们的“ T1”是const char*,它是const 指针,而不是 const指针。这里的实际类型是指针类型,所以很重要。

牢记第二行的Clang错误告诉我们了这一点:

error: non-const lvalue reference to type 'const char *' cannot bind to a value of unrelated type 'const char [6]'
    const char*& a = "hello";
                 ^    ~~~~~~~

关于成为非常量左值引用的部分正好是5.2 –在我们的例子中,左值是指向const的指针不是const!不像第一行。完全绑定到不相关类型的部分是¶5.1–我们的const char*不兼容且RHS为const char[6]或{ {em}指向指针数组转换后。

由于这个确切原因,或者没有这个原因,可以编译无错误的内容:

const char* const
除了

ISO C ++ 11 警告外,编译器允许一次通过(但不应该这样,因为字符串文字是'const char 6',我们不应该这样做)请先删除第一个char* const & a = "hello"; ),因为关于它的对象(指针)的引用现在是const

另一个有趣的事情是,一个const引用rvalue(没有“第二个const char* && a”)可以绑定到从< em>字符串文字,就像@StoryTeller提供的一样。这是为什么?由于array to pointer conversion:

的规则
  

类型为“ NT数组”的左值或右值 或“未知范围的数组”   的T“ 可以转换为”指向T的指针“的 prvalue

这里没有提及const或其他 cv-qualification 措词,但这仅在我们初始化右值引用时有效。