【问题标题】:Reference initialization in C++C++ 中的引用初始化
【发布时间】:2011-01-19 21:35:38
【问题描述】:

谁能向我解释一下为什么这两种说法有区别?

class A{};

const A& a = A();         // correct 

A& b = A();               // wrong

它说 从 A 类型的临时变量初始化 A& 类型的非常量引用无效

为什么const 在这里很重要?

【问题讨论】:

    标签: c++ reference lvalue rvalue const-reference


    【解决方案1】:

    非常量引用必须用左值初始化。如果你可以用临时变量来初始化它们,那么下面会做什么呢?

    int& foo = 5;
    foo = 6; // ?!
    

    const 引用具有延长裁判寿命的特殊属性,并且由于它们是const,因此您不可能尝试修改不在内存中的内容。例如:

    const int& foo = 5;
    foo = 6; // not allowed, because foo is const.
    

    请记住,引用实际上必须引用某些东西,而不仅仅是临时变量。例如,以下是有效的:

    int foo = 5;
    int& bar = foo;
    bar = 6;
    assert(foo == 6);
    

    【讨论】:

    • 等等,这是否意味着我可以使用const classA& ref = ReturnsClassAByValue();?我以为温度会在下一行消失。
    • 是的,你可以使用它。临时变量将持续与引用变量一样长:herbsutter.spaces.live.com/blog/cns!2D4327CC297151BB!378.entry
    • 是的,const 引用将临时对象的生命周期延长到引用的生命周期。在许多方面,您可以将const T& 视为const T——只是没有昂贵的复制;)
    【解决方案2】:

    这方面的术语有点混乱;您可能想进一步研究它们。不过,这是简短的答案:

    您正在将一个临时对象(调用类的构造函数的结果)分配给一个变量。临时对象是 R 值。您不能将 R 值分配给非常量引用。

    您可以将 R 值分配给 const 引用,尽管允许它的理由非常模糊。

    【讨论】:

      【解决方案3】:

      在 C++ 语言中,将非常量引用附加到右值是非法的,而将 const 引用附加到右值是完全可以的。例如,这是合法的

      const int& r = 5;
      

      虽然不是

      int &r = 5; // ERROR
      

      表达式A() 返回的A 类型的临时对象是一个右值,因此上述规则也适用于您的情况。

      【讨论】:

      • 右值是一个未命名的临时值,类似于函数的返回值。
      • @thebretness:不一定。例如,一个枚举常量是一个右值,但它是命名的
      【解决方案4】:

      对于临时/右值,您只能有一个 const 引用。

      您可以对非临时/左值进行非常量引用。

      A a;
      A& b = a;
      

      我认为这样做的原因是为了强调右值是暂时的这一事实,因为能够修改将暂时消失的东西几乎没有价值。

      【讨论】:

      • 授予;我认为 OP 正在寻找为什么会这样。
      【解决方案5】:

      因为标准是这样说的:

      §8.5.3.5 ...否则,引用应是对非易失性常量类型的左值引用...

      但是,如果你非常想要,你可以得到它:

      #include <iostream>
      int main()
      {
        const int & cr=5;
        int & r=const_cast<int &>(cr);
        r=6;
        std::cout<<r;
      }
      // outputs 6 with c++/clang++, Debian 8, amd64
      

      但请注意,假定的常量 cr 也不再是 const,并且您会产生未定义的行为。 (§1.9 (4))

      正如上面的代码所暗示的,这种差异没有技术原因。相反,设计师对用户将如何处理对临时对象的非常量引用做了噩梦。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-03-24
        • 1970-01-01
        • 2015-04-27
        • 1970-01-01
        • 2014-08-23
        • 1970-01-01
        • 2012-05-17
        • 1970-01-01
        相关资源
        最近更新 更多