C++11 auto declaration with and without pointer declarator

What's the difference between the types of bar1 and bar2?

int foo = 10;
auto bar1 = &foo;
auto *bar2 = &foo;

If both bar1 and bar2 are int*, does it makes sense to write the pointer declarator (*) in the bar2 declaration?


Solution 1:

The declarations are exactly equivalent. auto works (almost) the same as template type deduction. Putting the star explicitly makes the code a bit easier to read, and makes the programmer aware that bar2 is a pointer.

Solution 2:

Using auto * "documents intention". And auto *p = expr; can be deduced correctly only if expr returns pointer. Example:

int f();

auto q = f(); // OK

auto *p = f(); // error: unable to deduce 'auto*' from 'f()'

Solution 3:

There is a big difference when you use const qualifiers:

int i;

// Const pointer to non-const int
const auto ip1 = &i; // int *const
++ip1; // error
*ip1 = 1; // OK

// Non-const pointer to const int
const auto* ip2 = &i; // int const*
++ip2; // OK
*ip2 = 1; // error

Solution 4:

In this specific example both bar1 and bar2 are the same. It's a matter of personal preference though I'd say that bar2 is easier to read.

However, this does not hold true for references as seen in this example:

#include <iostream>
using namespace std;

int main() {
    int k = 10;
    int& foo = k;
    auto bar = foo; //value of foo is copied and loses reference qualifier!
    bar = 5; //foo / k won't be 5
    cout << "bar : " << bar << " foo : " << foo << " k : " << k << endl;
    auto& ref = foo;
    ref = 5; // foo / k will be 5
    cout << "bar : " << bar << " foo : " << foo << " k : " << k;
    return 0;
}

Solution 5:

As others said, they'll generate the same code. The asterisk is line noise (and makes it harder to switch from raw pointers to smart pointers if, for example, &foo is ever replaced by get_foo()). If you want to be explicit, then by all means, be explicit; but when you're using type inference, just let the compiler do its job. Lack of asterisks does not imply that an object isn't a pointer.