Sign in to follow this  
Demolit

Vector containing struct with pointer

Recommended Posts

This is probably a pointer problem, but I can't find a workaround this one. All I'm trying to do is create a vector of structs, then accessing a pointer in that struct via the vector, but I can't seem to do that. Here's the gist of my code:
typedef struct b
{
    int num;
} b_t;

typedef struct a
{
    b_t *b_p;
} a_t;

typedef struct main
{
    vector<a_t> *vec;
} main_t;

int main()
{
    main_t *test = new main_t;
    a_t* parent = new a_t;
    b_t* member = new b_t;
    member->num = 3;

    parent->b_p = member;

    test->vec = new vector<a_t>(1);

    test->vec->push_back(*parent);

    cout << test->vec->at(0).b_p->num << endl;
}


Before you ask why I'm using structs, I'm using a file which was previously written in C. I'd expect it should still work.

Share this post


Link to post
Share on other sites
Quote:
Original post by Demolit
Shortly after I posted I realised I didn't clear the vector before using push_back, would that be a problem?
No. A Vector's initial state is empty.

The first thing that jumps out at me about that code is that you should never new up a vector. Just declare the vector as a member of the struct (remove the *).
The cause of the crash though, is that you're adding 1 uninitialised item to the vector when you're newing it and the one you're pushing back is then put after the uninitialised one, at index 1, not 0.

Some fixed code:
typedef struct b
{
int num;
} b_t;

typedef struct a
{
b_t *b_p;
} a_t;

typedef struct main
{
vector<a_t> vec;
} main_t;

int main()
{
main_t *test = new main_t;
a_t* parent = new a_t;
b_t* member = new b_t;
member->num = 3;

parent->b_p = member;

test->vec.push_back(*parent);

cout << test->vec.at(0).b_p->num << endl;
}

Share this post


Link to post
Share on other sites
It is perfectly fine to use 'struct' in C++, but the 'typedef struct' idiom is useless in C++. C++ does not put struct names in their own namespace, so you never have to write 'struct X' when declaring an instance of the X struct (even without typedef magic). Also, using 'main' as a name for anything besides the main() function is sketchy. :)

As iMalc noted, vectors do not require any special initialization with .clear() or anything else; in C++, objects are supposed to be usable from the get-go - that's what constructors are for - and clean up their own messes - that's what destructors are for. Here, .clear() would fix your bug, but it would miss the point entirely: the whole point of using .push_back to add things to a vector is that you don't need to pre-allocate the space. And the constructor for vector that accepts an element-count pre-loads the vector with default-constructed instances; it doesn't simply allocate space.

And yeah, there's no point to using dynamic allocation for the vector instance itself. In the test code, there isn't even a reason to allocate the 'b' instance dynamically; it's perfectly possible for the 'a' instance to store a pointer to a stack-allocated 'b'. (However, you really, really want to think more about what you're doing here; don't just cram raw pointers into structures without a detailed understanding of what the "ownership policy" will be.)

Basically: you should never, in your first pass of the code, even think about "allocating" anything when you use a vector. :)


#include <iostream>
#include <vector>

struct b_t {
int num;
}; // you do unfortunately still need this semicolon...

struct a_t {
b_t* b_p; // C++ style normally puts the pointer on the type name.
};

struct m_t {
std::vector<a_t> vec;
// Probably a good idea not to rely on 'using' declarations within struct
// declarations. After all, it'll probably be moved to a header, and headers
// should never use using-declarations because then there is no way for a
// source file which #includes the header to "un-use" the declaration.
};

int main() {
b_t member = { 3 }; // aggregate initialization works in C++ for certain
// very limited cases, called POD structs. The definition of what is POD
// will expand in C++0x.
a_t parent;
parent.b_p = &member;

m_t test;
test.vec.push_back(parent);

std::cout << test.vec.at(0).b_p->num << std::endl;
}

Share this post


Link to post
Share on other sites
Quote:
Original post by nobodynews
Quote:
Original post by SiCrane
The ghosts of Gilbert and Sullivan possessing your computer?


I hate when that happens. Stupid undefined behavior.

Implementation-defined, not undefined. The Standard specifies that either NULL is returned, or Gilbert and Sullivan possess your computer.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this