C++11 auto: what if it gets a constant reference?
C++ReferenceC++11AutoC++ Problem Overview
Please take a look at the following simple code:
class Foo
{
public:
Foo(){}
~Foo(){}
Foo(const Foo&){}
Foo& operator=(const Foo&) { return *this; }
};
static Foo g_temp;
const Foo& GetFoo() { return g_temp; }
I tried to use auto
like this:
auto my_foo = GetFoo();
I expected that my_foo
will be a constant reference to Foo
, which is the return type of the function. However, the type of auto
is Foo
, not the reference. Furthermore, my_foo
is created by copying g_temp
. This behavior isn't that obvious to me.
In order to get the reference to Foo
, I needed to write like this:
const auto& my_foo2 = GetFoo();
auto& my_foo3 = GetFoo();
Question: Why does auto
deduce the return type of GetFoo
as an object, not a reference?
C++ Solutions
Solution 1 - C++
Read this article: Appearing and Disappearing consts in C++
> Type deduction for auto variables in C++0x is essentially the same as > for template parameters. (As far as I know, the only difference > between the two is that the type of auto variables may be deduced from > initializer lists, while the types of template parameters may not be.) > Each of the following declarations therefore declare variables of type > int (never const int): >
auto a1 = i;
auto a2 = ci;
auto a3 = *pci;
auto a4 = pcs->i;
> > During type deduction for template parameters and auto variables, only > top-level consts are removed. Given a function template taking a > pointer or reference parameter, the constness of whatever is pointed > or referred to is retained: >
template<typename T>
void f(T& p);
int i;
const int ci = 0;
const int *pci = &i;
f(i); // as before, calls f<int>, i.e., T is int
f(ci); // now calls f<const int>, i.e., T is const int
f(*pci); // also calls f<const int>, i.e., T is const int
> > This behavior is old news, applying as it does to both C++98 and > C++03. The corresponding behavior for auto variables is, of course, > new to C++0x: >
auto& a1 = i; // a1 is of type int&
auto& a2 = ci; // a2 is of type const int&
auto& a3 = *pci; // a3 is also of type const int&
auto& a4 = pcs->i; // a4 is of type const int&, too
Since you can retain the cv-qualifier if the type is a reference or pointer, you can do:
auto& my_foo2 = GetFoo();
Instead of having to specify it as const
(same goes for volatile
).
Edit: As for why auto
deduces the return type of GetFoo()
as a value instead of a reference (which was your main question, sorry), consider this:
const Foo my_foo = GetFoo();
The above will create a copy, since my_foo
is a value. If auto
were to return an lvalue reference, the above wouldn't be possible.