Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++11 auto: what if it gets a constant reference?

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?

like image 709
minjang Avatar asked Aug 21 '11 13:08

minjang


People also ask

Can reference variables be constant?

A const reference is actually a reference to const. A reference is inherently const, so when we say const reference, it is not a reference that can not be changed, rather it's a reference to const. Once a reference is bound to refer to an object, it can not be bound to refer to another object.

Does Auto include const?

The auto keyword by itself represents a value type, similar to int or char . It can be modified with the const keyword and the & symbol to represent a const type or a reference type, respectively.

Can references be const?

The grammar doesn't allow you to declare a “const reference” because a reference is inherently const . Once you bind a reference to refer to an object, you cannot bind it to refer to a different object.

What does constant reference mean?

A Constant Reference is actually a Reference to a Constant. A constant reference/ Reference to a constant is denoted by: int const &i = j; //or Alternatively const int &i = j; i = 1; //Compilation Error. It basically means, you cannot modify the value of type object to which the Reference Refers.


1 Answers

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.

like image 94
someguy Avatar answered Oct 16 '22 00:10

someguy