Passing int&& to f(int&&)

后端 未结 3 1688
小蘑菇
小蘑菇 2020-12-06 09:34

What is exactly happening here? Why is this an error?

void f(int &&);

int && i = 5;

f(i);

Isn\'t it a bit counterintuitiv

相关标签:
3条回答
  • 2020-12-06 10:11

    There's a basic distinction here between is a and binds a. For example:

    void f(int &&);
    

    declares a function accepting a parameter that can only be initialized with an rvalue reference to a (type convertible to) int.

    int && i = 5;
    

    declares an lvalue that can only be initialized with an rvalue reference to a (type convertible to) int. Thus, in simple terms,

    f(i);
    

    tries to pass an lvalue reference to an int to a function accepting only rvalue references to an int. So it doesn't compile.

    To tell the compiler to cast an lvalue to an rvalue, thereby utilizing move constructors where applicable (though not in the case of an int), you can use std::move().

    f(std::move(i));
    
    0 讨论(0)
  • 2020-12-06 10:28

    I see why you are confused. The thing to remember is that whenever you have a variable name, you have an l-value.

    So when you say:

    int i = 0; // lvalue (has a name i)
    

    And also

    int&& i = 0; // lvalue (has a name i)
    

    So what is the difference?

    The int&& can only bind to an r-value so:

    int n = 0;
    int i = n; // legal
    

    BUT

    int n = 0;
    int&& i = n; // BAD!! n is not an r-value
    

    However

    int&& i = 5; // GOOD!! 5 is an r-value
    

    So when passing i to f() in this example you are passing an l-value, not an r-value:

    void f(int &&);
    
    int&& i = 5; // i is an l-value
    
    f(i); // won't accept l-value
    

    The situation is actually a little more complicated than I have presented here. If you are interested in a fuller explanation then this reference is quite thorough: http://en.cppreference.com/w/cpp/language/value_category

    0 讨论(0)
  • 2020-12-06 10:29

    Does it have a name?
    Is it addressable?

    If the answer to both is "yes", it's a L-Value.

    In this snippet: i has a name, i has an address (you can write &i), so it's a l-value.

    f(&&) gets r-value-reference as a parameter, so you need to turn l-value to r-value reference, which can be done with std::move.

    f(std::move(i));
    
    0 讨论(0)
提交回复
热议问题