由于字符串文字被认为是左值,为什么绑定左值引用必须是const?

ela*_*lau 14 c++ reference string-literals lvalue language-lawyer

我知道有些主题与此类似(例如).

本主题中给出的示例如下:

std::string & rs1 = std::string();
Run Code Online (Sandbox Code Playgroud)

显然,std :: string()是一个右值.但是,我的问题是为什么s1合法而s2不合法?

const std::string& s1 = "String literal";
std::string& s2 = "String literal";
Run Code Online (Sandbox Code Playgroud)

该标准清楚地表明字符串文字是左值(这是可以理解的,因为它们在技术上是const char*幕后).当我编译s2时,我得到以下内容:

prog.cpp:4:19: error: invalid initialization of non-const reference of type
'std::string& {aka std::basic_string<char>&}' from an rvalue of type
'const char*' std::string& s2 = "String literal";
Run Code Online (Sandbox Code Playgroud)

我理解左值和右值的标准定义是互斥的,所以这可能是编译器的错误吗?我在这个例子中使用gcc 4.9.2.这也是文字真的是xvalue的情况之一吗?

Col*_*mbo 20

问题是字符串文字不是类型std::string或子类 - 它是类型
char const[N].因此,初始化程序的类型与引用的目标类型不是引用兼容的,并且必须创建临时文件并将其绑定到引用.

但是,临时值不​​能绑定到非常量左值引用.即你的情况相当于

std::string& s = std::string("Abcdefg");
Run Code Online (Sandbox Code Playgroud)

即使根据你的说法,这显然是不正确的.


实际上它不起作用的确切原因并不是因为临时数不能绑定到非常量左值引用,而是非常量左值引用的初始化char const[N]符合某些在这种情况下无法满足的要求,[dcl. init.ref]/5:

参考输入" CV1 T1 "是通过类型"的表达初始化CV2 T2 "如下:

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

    • 是左值(但不是位字段),以及" CV1 T1 "是参考兼容" CV2 T2 "或
    • 具有类类型(即,T2是类类型),其中T1与T2不是引用相关的,并且可以隐式转换为类型为"cv3 T3"的左值,其中" cv1 T1 "与" cv3 "引用兼容T3" 106(通过枚举适用的转换函数(13.3.1.6)并通过重载决策(13.3)选择最佳转换函数来选择此转换),

    然后,引用绑定到第一种情况下的初始化表达式lvalue和第二种情况下转换的左值结果(或者,在任何一种情况下,绑定到对象的相应基类子对象).

  • 否则,引用应是对非易失性const类型的左值引用(即,cv1应为const),或者引用应为右值引用.

    • [..]

106)这需要转换函数(12.3.2)返回引用类型.


Mar*_*som 10

字符串文字可以是左值,但它不是string对象.有一个临时string的创建,这是一个右值.

  • 对此,`s1'利用以下规则:将const引用绑定到临时对象将临时对象的生存期延长到引用的范围,而将非const引用绑定到临时对象则是错误的。 (2认同)