Q:

C++ getting struct from vector with & returns pointer to non-initialized struct

The function structFromVector() returns a struct from a vector of structs. If you compile the code below, then foo1Ptr->a is an empty vector, but foo2Ptr->a is a vector whose only element is 1. Why isn't the struct initialized in the first case? 
If a is an int instead of a vector and instead of a.push_back(1); you use a = 1;, then both foo1Ptr->a and foo2Ptr->a are equal to 1. Why does it work in this case and not in the first case?
struct Foo {
    std::vector<int> a;

    Foo() {
        a.push_back(1);
    }
};

std::vector<Foo> fooList;

Foo structFromVector() {
    return fooList[0];
}

int main() {
    fooList.push_back(Foo());

    Foo * foo1Ptr = &structFromVector();

    Foo foo2 = structFromVector();
    Foo * foo2Ptr = &foo2;
}

A:

You are attempting to initialize a pointer with a temporary Foo object here:
Foo * foo1Ptr = &structFromVector();

Your compiler should have rejected this code (taking the address of a temporary.)
If it were to compile, after this line, one could imagine that foo1Ptr would point to a non-existent object (it would be a dangling pointer). Do de-reference it would invoke undefined behaviou. Still, discussing what a non-conforming implementation would do is quite speculative.
So, don't bind a pointer to a temporary, even if your compiler lets you do it.
One solution, which is probably what you were intending to do, is to return a reference to the vector's element:
Foo& structFromVector() {
    return fooList[0];
}

This reference is valid as long as you don't perform an operation on the vector that invalidates it (e.g. increasing its size such that it re-allocates.)

A:

Because you have undefined behavior in your code.
Here:
Foo * foo1Ptr = &structFromVector();

structFromVector returns a temp object and foo1Ptr becomes a pointer to this temp object. After ;, this temp object is destroyed and the pointer is called dangling (in other words - it becomes invalid).
In the second case, 
Foo foo2 = structFromVector();
Foo * foo2Ptr = &foo2;

foo2 is now a copy of this temp object and foo2Ptr points to this copy. So, the pointer is valid (while foo1Ptr is invalid). The copy will be alive till the end of the scope - in this case, till main's }.
The reason it "works" with int is, again, the UB (Undefined Behavior) - anything can happen.

EDIT Well, it appears to be ill-formed code, as the compiler really should have rejected that code. But as it hasn't, it's still UB.

