error: invalid initialization of non-const reference of type ‘int&’ from an rvalue of type ‘int’

前端 未结 5 1544
盖世英雄少女心
盖世英雄少女心 2020-11-28 18:42

Wrong form:

int &z = 12;

Correct form:

int y;
int &r = y;

Question:

相关标签:
5条回答
  • 2020-11-28 19:16

    12 is a compile-time constant which can not be changed unlike the data referenced by int&. What you can do is

    const int& z = 12;
    
    0 讨论(0)
  • 2020-11-28 19:27

    C++03 3.10/1 says: "Every expression is either an lvalue or an rvalue." It's important to remember that lvalueness versus rvalueness is a property of expressions, not of objects.

    Lvalues name objects that persist beyond a single expression. For example, obj , *ptr , ptr[index] , and ++x are all lvalues.

    Rvalues are temporaries that evaporate at the end of the full-expression in which they live ("at the semicolon"). For example, 1729 , x + y , std::string("meow") , and x++ are all rvalues.

    The address-of operator requires that its "operand shall be an lvalue". if we could take the address of one expression, the expression is an lvalue, otherwise it's an rvalue.

     &obj; //  valid
     &12;  //invalid
    
    0 讨论(0)
  • 2020-11-28 19:27

    References are "hidden pointers" (non-null) to things which can change (lvalues). You cannot define them to a constant. It should be a "variable" thing.

    EDIT::

    I am thinking of

    int &x = y;
    

    as almost equivalent of

    int* __px = &y;
    #define x (*__px)
    

    where __px is a fresh name, and the #define x works only inside the block containing the declaration of x reference.

    0 讨论(0)
  • 2020-11-28 19:30

    Non-const and const reference binding follow different rules

    These are the rules of the C++ language:

    • an expression consisting of a literal number (12) is a "rvalue"
    • it is not permitted to create a non-const reference with a rvalue: int &ri = 12; is ill-formed
    • it is permitted to create a const reference with a rvalue: in this case, an unnamed object is created by the compiler; this object will persist as long as the reference itself exist.

    You have to understand that these are C++ rules. They just are.

    It is easy to invent a different language, say C++', with slightly different rules. In C++', it would be permitted to create a non-const reference with a rvalue. There is nothing inconsistent or impossible here.

    But it would allow some risky code where the programmer might not get what he intended, and C++ designers rightly decided to avoid that risk.

    0 讨论(0)
  • 2020-11-28 19:34
    int &z = 12;
    

    On the right hand side, a temporary object of type int is created from the integral literal 12, but the temporary cannot be bound to non-const reference. Hence the error. It is same as:

    int &z = int(12); //still same error
    

    Why a temporary gets created? Because a reference has to refer to an object in the memory, and for an object to exist, it has to be created first. Since the object is unnamed, it is a temporary object. It has no name. From this explanation, it became pretty much clear why the second case is fine.

    A temporary object can be bound to const reference, which means, you can do this:

    const int &z = 12; //ok
    

    C++11 and Rvalue Reference:

    For the sake of the completeness, I would like to add that C++11 has introduced rvalue-reference, which can bind to temporary object. So in C++11, you can write this:

    int && z = 12; //C+11 only 
    

    Note that there is && intead of &. Also note that const is not needed anymore, even though the object which z binds to is a temporary object created out of integral-literal 12.

    Since C++11 has introduced rvalue-reference, int& is now henceforth called lvalue-reference.

    0 讨论(0)
提交回复
热议问题