初始化引用 虽然我认为我理解C++中的 rValue/Cuth>和 LValue/Cuth>语义,但我似乎一遍又一遍地反复尝试,证明我不知道蹲下。
然而,有两个非常简单和基本的问题,我不明白它们是如何工作的。在我编译它们之前,我认为没有一个是可以的,在我看到初始化引用 虽然我认为我理解C++中的 rValue/Cuth>和 LValue/Cuth>语义,但我似乎一遍又一遍地反复尝试,证明我不知道蹲下。,c++,reference,C++,Reference,然而,有两个非常简单和基本的问题,我不明白它们是如何工作的。在我编译它们之前,我认为没有一个是可以的,在我看到(1)可以工作之后,我认为(2)也可以工作。但是,(1)起作用,(2)不起作用: (1) const std::string &s = "asd"; 这里发生了什么?我的猜测是,一个临时的常量字符串对象是由“asd”构造的,然后s被绑定到该临时对象。但是临时对象不是在这一行之后就被销毁了吗,这样我们就剩下一个无效的引用了 当我删除const限定符时: (2) std::stri
(1)
可以工作之后,我认为(2)
也可以工作。但是,(1)
起作用,(2)
不起作用:
(1) const std::string &s = "asd";
这里发生了什么?我的猜测是,一个临时的常量字符串
对象是由“asd”
构造的,然后s
被绑定到该临时对象。但是临时对象不是在这一行之后就被销毁了吗,这样我们就剩下一个无效的引用了
当我删除const
限定符时:
(2) std::string &s = "asd";
我收到一个编译器错误(VS 2013):无法从“const char[4]”转换为“std::string&
。这似乎反驳了我的理论,因为根据它(我的猜测),一个临时的字符串
对象将由“asd”
构造,然后分配给它,这不会产生任何编译错误
综上所述:
- 绑定到什么
绑定到的对象的寿命是多少s
< > > <代码>(1)<代码>编译>代码>(2)< /C>不(在代码< STD::String < /Cube >中是否有一些转换运算符?或者是C++语义?
(2)
不起作用,因为“asd”
是一个字符常量[]
。编译器将隐式地(实际上)将其转换为一个临时的string
rvalue。不能将非常量引用分配给将立即超出范围的值。所以你的分析是正确的
对于(1)
我不得不自己做一些查找,但我想我在这里找到了答案:
标准似乎允许在将临时引用绑定到常量引用时进行复制。未扩展,我同意:)因此将再次隐式转换为临时字符串
rvalue,并且由于引用现在是const
,因此将复制此rvalue以使其保持不变。TL;博士
- 绑定到什么上
- 绑定到的对象的寿命是多少
std::string
,该字符串的有效期与s
一样长
什么使(1)编译和(2)不编译
您不能对非左值进行非常量引用
相关引用
引用第8.5.3节[dcl.初始参考]:
对类型“cv1 T1
”的引用由类型的表达式初始化
“cv2 T2
”如下所示:
- […剪断,不相关..]
- 否则[如果右侧不是左值],则参考应是对非易失常数类型的左值参考(即
应为常量),或参考应为右值参考。cv1
- […剪断,不相关..]
- 否则,使用初始化器表达式创建并初始化类型为“
T1”的临时变量 非引用副本初始化规则(8.5)。参考文献 然后绑定到临时。如果T1与T2、cv1相关 应具有与相同或更高的cv资格 比,cv2。如果T1是与T2相关的参考,且参考是 右值引用时,初始值设定项表达式不得为左值cv1
const char*
转换为std::string
,这将引入一个类型为std::string
的临时变量。由于这不是左值,因此引用应为const
。这就得出了(2)不起作用的原因
在整个生命周期中,请看12.2[class.temporary]:
有两种情况下,时间单位在完全表达结束时的不同点被销毁。[……]
第二个上下文是将引用绑定到临时上下文。引用绑定到的临时对象或作为引用绑定到的子对象的完整对象的临时对象在引用的生存期内持续存在[…]
这意味着只要您的const
reference,临时文件就会被保存。这就是(1)起作用的原因
请注意,标准中有更多的细节,其中包括一些角落案例,因此您可能希望完整阅读这些部分
绑定到什么
到一个临时的std::string
,如您所猜测的,它是由字符串文本构造的
绑定到s
的对象的寿命是多长
临时对象的生存期将延长以匹配引用的生存期。通常,临时性在创造它们的完整表达结束时被摧毁;这是该规则的一个例外
什么使(1)编译和(2)不编译
另一个语言规则:临时变量不能绑定到非
const
引用。这条规则有点古怪,但很有用:如果您无意中修改了临时对象而不是更持久的对象,它可以防止出现细微的错误。这是一个常量引用。这是一个巨大的差别,因为你正在使(1)s成为右值。函数f1(常量字符串&s)
和f2(字符串&s)
也是如此,在第一种情况下,您可以调用f2(“我的文本常量”)
,但另一个函数会失败。