Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

auto* vs. auto in C++ [duplicate]

Given my variable being a pointer, if I assign it to a variable of "auto" type, do I specify the "*" ?

std::vector<MyClass> *getVector(); //returns populated vector
//...

std::vector<MyClass> *myvector = getVector();  //assume has n items in it
auto newvar1 = myvector;

// vs:
auto *newvar2 = myvector;

//goal is to behave like this assignment:
std::vector<MyClass> *newvar3 = getVector();

I'm a bit confused on how this auto works in c++11 (this is a new feature to c++11, right?)

Update: I revised the above to better clarify how my vector is really populated in a function, and I'm just trying to assign the returned pointer to a variable. Sorry for the confusion

like image 872
Dolan Antenucci Avatar asked Oct 07 '12 22:10

Dolan Antenucci


3 Answers

There is a, perhaps subtle, difference between auto and auto* when it comes to constness.

int i;
const auto* p = &i;

is equivalent to

int i;
const int* p = &i;

whereas

int i;
const auto p = &i;

is equivalent to

int i;
int* const p = &i;

This has the following effect:

void test(int a) {
    const auto* p1 = &a;

    *p1 = 7;               // Error
    p1 = nullptr;          // OK

    const auto p2 = &a;

    *p2 = 7;               // OK
    p2 = nullptr;          // Error
}
like image 63
Pibben Avatar answered Sep 24 '22 05:09

Pibben


auto newvar1 = myvector;

// vs:
auto *newvar2 = myvector;

Both of these are the same and will declare a pointer to std::vector<MyClass> (pointing to random location, since myvector is uninitialized in your example and likely contains garbage). So basically you can use any one of them. I would prefer auto var = getVector(), but you may go for auto* var = getVector() if you think it stresses the intent (that var is a pointer) better.

I must say I never dreamt of similar uncertainity using auto. I thought people would just use auto and not think about it, which is correct 99 % of the time - the need to decorate auto with something only comes with references and cv-qualifiers.

However, there is slight difference between the two when modifies slightly:

auto newvar1 = myvector, newvar2 = something;

In this case, newvar2 will be a pointer (and something must be too).

auto *newvar1 = myvector, newvar2 = something;

Here, newvar2 is the pointee type, eg. std::vector<MyClass>, and the initializer must be adequate.

In general, if the initializer is not a braced initializer list, the compiler processes auto like this:

  1. It produces an artificial function template declaration with one argument of the exact form of the declarator, with auto replaced by the template parameter. So for auto* x = ..., it uses

    template <class T> void foo(T*);
    
  2. It tries to resolve the call foo(initializer), and looks what gets deduced for T. This gets substituted back in place of auto.

  3. If there are more declarators in a single declarations, this is done for all of them. The deduced T must be the same for all of them...

like image 24
jpalecek Avatar answered Sep 22 '22 05:09

jpalecek


auto newvar1 = *myvector;

This is probably what you want, which creates a copy of the actual vector. If you want to have a reference instead write auto& newvar1 = *myvector; or to create another pointer to the same vector use auto newvar1 = myvector;. The difference to your other attempt auto *newvar1 = myvector; is that the latter once forces myvector to be of pointer type, so the following code fails:

std::vector<int> v1;
auto* v2 = v1; // error: unable to deduce ‘auto*’ from ‘v1’
like image 40
Stacker Avatar answered Sep 24 '22 05:09

Stacker