References C++ | Sololearn: Learn to code for FREE!
New course! Every coder should learn Generative AI!
Try a free lesson
+ 3

References C++

I am having trouble understanding why certain types bind to &, others to &&, and some to both. I attached a sample code, with comments that indicate what does and doesn't work, and I was hoping someone could explain simply why this is the case? https://code.sololearn.com/cZnJgXoHYSEl

20th Dec 2021, 8:29 PM
Edward Finkelstein
Edward Finkelstein - avatar
5 Answers
+ 3
This is because "vector <bool>" is not what you think it is. It's special because the language standards allow implementation writers to space optimize the containers of type bool ( how they actually do it is implementation dependent ) You can check cppreference to see the extent of flexibility standards allow for it 👇 https://en.cppreference.com/w/cpp/container/vector_bool The perticular case you are experiencing on your perticular implementation ( gcc ) here is when the elements are not conventionally stored but are rather stored such that each element requires a single bit ( rather than a byte ) and class std::vector<bool>::reference is exposed as a method of accessing individual bits, so operator[ ] doesn't return a reference ( &bool ) but a temporary value instead ( which due to obvious reasons is not allowed to bind to an lvalue reference )
21st Dec 2021, 5:33 AM
Arsenic
Arsenic - avatar
+ 1
An rvalue reference behaves just like an lvalue reference except that it can bind to a temporary (an rvalue), whereas you can not bind a (non const) lvalue reference to an rvalue. Ex& rEx = Ex(); // Error! Ex&& rEx = Ex(); // Ok Rvalue references can be used to extend the lifetimes of temporary objects (note, lvalue references to const can extend the lifetimes of temporary objects too, but they are not modifiable through them #include <iostream> #include <string>   int main() { std::string s1 = "Test"; // std::string&& r1 = s1; // error: can't bind to lvalue   const std::string& r2 = s1 + s1; // okay: lvalue reference to const extends lifetime // r2 += "Test"; // error: can't modify through reference to const   std::string&& r3 = s1 + s1; // okay: rvalue reference extends lifetime r3 += "Test"; // okay: can modify through reference to non-const std::cout << r3 << '\n'; } you can learn more at https://en.cppreference.com/w/cpp/language/reference
22nd Dec 2021, 5:20 PM
Smith Welder
Smith Welder - avatar
+ 1
https://code.sololearn.com/csBOra8H2329/?ref=app
22nd Dec 2021, 5:51 PM
Smith Welder
Smith Welder - avatar
+ 1
Edward Finkelstein I think Arsenic has done a great job at explaining the first case. When it comes to vector<bool>, its access operators in gcc return a temporary object of type std::vector<bool>::reference which cannot be attached to an lvalue reference.(Try replacing 'bool' with 'vector<bool>::reference' to convince yourself that an actual object is what is being returned and not a bool). For the next two cases, I think what's happening is quite obvious. The range-based for loop returns an lvalue on each iteration, which can only be assigned to an lvalue reference. The last case seems strange because of the way the 'auto' keyword works. I'm not going to try and explain how auto works since it's a slightly more advanced topic and there are a ton of good resources out there But basically auto works in a similar way to how the template type resolution works. The 'auto&& i' in the first range-based for loop behaves like a template function having a universal reference.
24th Dec 2021, 7:28 AM
Anthony Maina
Anthony Maina - avatar
+ 1
[Cont.] as its parameter e.g. template<typename T> void f(T&& arg); Such a function can receive both rvalue and lvalue reference arguments. The 'auto& i' in the second range-based for loop behaves like a template function having an lvalue reference as it's parameter. e.g template<typename T> void f(T& arg); Such a function can only receive an lvalue reference as it's arguments. Since we have already established that access operators of all vector types except vector<bool> return an lvalue, the object returned on each and every iteration can be assigned to the the lvalue reference i without issues.
24th Dec 2021, 7:38 AM
Anthony Maina
Anthony Maina - avatar