What is the difference between writing:
auto my_var = [expression];
and
auto& my_var = [expression];
A) What is being communicated ?
B) Is the first version guaranteed to be a copy ? (when, when not ?)
C) When should you use the second 'auto&' ?
Update:
One example is when expression evaluates to a reference:
#include <vector>
int main() {
auto ints = std::vector{-1};
auto front_int = ints.front();//front returns a reference, but 'auto' doesn't reflect that (giving us a copy instead)
front_int = 0;
return ints.front();//returns '-1', we didn't update the vector
}
This may not seem intuitive at first (while it makes sense if you try to look at the broader picture). To 'fix', we need to use auto&
version, - but why is that exactly ?
What is being communicated ?
The type of my_var
is being communicated. my_var
is a variable that is being declared. More specifically, the ampersand (or lack thereof) communicates whether the type is a reference or not.
is the first version guareenteed to be a copy ?
It is guaranteed to be a distinct object.
It is not guaranteed to copy however. That depends on the expression. If it is a prvalue, then there will not be a copy since C++17; The variable will be initialised by the expression directly. Otherwise there is a copy (or move if the type has a move constructor and if the expression is an xvalue or if it is prvalue prior to C++17) as far as the abstract machine is concerned. But that copy / move may be elided in practice in some cases.
An example demonstrating lack of any copying. Following program is well-formed in C++17:
struct not_opyable_nor_movable {
not_opyable_nor_movable() = default;
not_opyable_nor_movable(not_opyable_nor_movable&) = delete;
not_opyable_nor_movable(not_opyable_nor_movable&&) = delete;
};
not_opyable_nor_movable function() {
return {};
}
int main() {
auto my_var = function();
}
when should you use the second 'auto&' ?
When you want to declare an lvalue reference. Example:
int foo{};
auto& myvar = foo;
myvar = 42; // foo is now 42
we need to use auto& version, -but why is that exactly ?
Because it seems that you want to make changes to the object referred by the result of the function call. To do that, you must make the modification through a reference. The ampersand is used to declare a reference.