Implicit conversion : const reference vs non-const reference vs non-reference

前端 未结 2 434
春和景丽
春和景丽 2020-12-30 08:07

Consider this code,

struct A {};
struct B {  B(const A&) {} };
void f(B)
{
    cout << \"f()\"<

        
相关标签:
2条回答
  • 2020-12-30 08:37

    I would like to hear reasons, rationale and reference(s) from the language specification

    Is The Design and Evolution of C++ sufficient?

    I made one serious mistake, though, by allowing a non-const reference to be initialized by a non-lvalue [comment by me: that wording is imprecise!]. For example:

    void incr(int& rr) { ++rr; }
    
    void g()
    {
        double ss = 1;
        incr(ss);    // note: double passed, int expected
                     // (fixed: error in release 2.0)
    }
    

    Because of the difference in type the int& cannot refer to the double passed so a temporary was generated to hold an int initialized by ss's value. Thus, incr() modified the temporary, and the result wasn't reflected back to the calling function [emphasis mine].

    Think about it: The whole point of call-by-reference is that the client passes things that are changed by the function, and after the function returns, the client must be able to observe the changes.

    0 讨论(0)
  • 2020-12-30 08:46

    The problem is that the implicit conversion from a to a B object yields an rvalue. Non-const references can only bind to lvalues.

    If B had a default constructor you would get the same behavior if you change the f(a) call to f(B()).

    --

    litb provides a great answer to what is an lvalue: Stack Overflow - often used seldom defined terms: lvalue

    GotW #88: A Candidate For the “Most Important const”

    Stack Overflow - How come a non-const reference cannot bind to a temporary object?

    --

    To explain with references to the standard how those function calls fail or succeed would be excessively long. The important thing is how B& b = a; fails while const B& b = a; does not fail.

    (from draft n1905)

    A reference to type “cv1 T1” is initialized by an expression of type “cv2 T2” as follows:
    - [is an lvalue and is either reference compatible or implicitly convertible to an lvalue of a reference compatible type...]
    - Otherwise, the reference shall be to a non-volatile const type (i.e., cv1 shall be const).

    Here's a case where something is convertible to an lvalue of reference compatible type.

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