初始化引用 虽然我认为我理解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
      应为常量)
      ,或参考应为右值参考。
      • […剪断,不相关..]
      • 否则,使用初始化器表达式创建并初始化类型为“
        cv1
        T1”的临时变量 非引用副本初始化规则(8.5)。参考文献 然后绑定到临时。如果T1与T2、cv1相关 应具有与相同或更高的cv资格 比,cv2。如果T1是与T2相关的参考,且参考是 右值引用时,初始值设定项表达式不得为左值
    在所有情况下,最后一种情况除外(即,创建和初始化 临时(从初始值设定项表达式中),引用称为 直接绑定到初始值设定项表达式

    在本例中,您需要将
    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(“我的文本常量”)
    ,但另一个函数会失败。