Sign in to follow this  
evanofsky

methinks i don't understand pointers

Recommended Posts

evanofsky    2913
I've read all the books, gotten the t-shirt and everything, and I still don't quite get it. Especially about pointer arrays. Here's a hypothetical example:
class Object {
   void DoSomething();
};

void Object::DoSomething() {
   // whatever
}

int main() {
   Object** list; // an array of pointers to Objects

   list = new Object*[num_objects];

   for(int i = 0; i < num_objects; i++) {
      InitObject(&(list[i]));
   }

   list[random_number]->DoSomething();
}
Suppose hypothetically that it crashes when I call DoSomething(). I'm probably doing something embarassingly wrong; please enlighten me!

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster

class Object {
void DoSomething();
};

void Object::DoSomething() {
// whatever
}

int main() {
Object** list; // an array of pointers to Objects

list = new Object*[num_objects];

for(int i = 0; i < num_objects; i++)
{
list[i] = new Object()
InitObject(list[i]);
}

list[random_number]->DoSomething();
}



Share this post


Link to post
Share on other sites
Kalasjniekof    246
I think you're overcomplicating things. This should work just the same:


class Object {
void DoSomething();
};

void Object::DoSomething() {
// whatever
}

int main() {
Object *list; // an array of pointers to Objects

list = new Object[num_objects];

for(int i = 0; i < num_objects; i++) {
InitObject(&(list[i]));
}

list[random_number].DoSomething();
}


Share this post


Link to post
Share on other sites
Agony    3452
What does InitObject() do? Does it actually create (as in use new to create) instances of objects that inherit from Object? If so, then you should supposedly be fine. Because it looks like InitObject() takes the address of a pointer, that means that InitObject() can actually change the value of the pointer, which would be necessary if it were using new to create new instances.

However, if InitObject() is only meant to take an already existing instance of an object, and set some values in it and such, then you have a problem. When you new the array, what you get is an array of pointers, but all the pointers are random, just like any uninitialized variable. Until you actually create some objects, or point to objects that have already been created, you won't be able to use those pointers for anything, or else you'll get memory access violation errors.

One possibility is that InitObject() is attempting to create objects, but sometimes it doesn't, and it might possibly set the pointer to NULL. Accessing a NULL pointer with your DoSomething() call will also cause a memory access violation error. Maybe you should be checking your pointer, to make sure it isn't NULL, before you call DoSomething().

Share this post


Link to post
Share on other sites
snk_kid    1312
Quote:
Original post by evanofsky
Thanks a bunch! Except, what happens if "Object" is abstract and you can't create instances of it?


If "object" is an abstact class (its non-instacable) then you instantiate the concrete types and assign them to those pointers:


struct foo {
virtual void do_do() = 0;
virtual ~foo() {}
};

struct bar : foo {
void do_do() {}
};


//....
foo** f = new foo*[N];

f[index] = new bar;

f[index]->do_do();
//...
delete f[index];

delete[] f;
///...


You'll need to read up on sub-type polymorphism.

Notice the destructor is virtual, you should do this if you intend on invoking delete on pointers to base classes, otherwise you may end up causing resource leaks.

Can i suggest 2 other things, in C++ for dynamic arrays in general prefer std::vector, when storing polymorphic types in standard library containers you have to store pointers so i recommend you look into smart pointers aswell. Boost library has a package of smart pointers you can use and some of them are currently being reviewed to be part of the C++ standard aswell, quick example:


struct foo { virtual ~foo() = 0; };
struct bar : foo {};

#include <boost/shared_ptr.hpp>
#include <vector>


//...
typedef boost::shared_ptr<foo> foo_ptr;

std::vector<foo_ptr> foos;

foo.reserve(num_objects);

foo_ptr f(new bar);
foos.push_back(f);

f.reset(new bar);
foos.push_back(f);

Share this post


Link to post
Share on other sites
evanofsky    2913
Thanks for the tips, snk_kid. I know how std::vector works, I just hadn't thought to use it in this scenario.

I'm gonna have to stop being hypothetical.

"Object" is an abstract, non-instantiable direct3d object. Init_Object() is a D3D function that allocates and sets the object. This may clear a few things up for you. :)

Thanks for the replies! I'll try out your ideas.

Share this post


Link to post
Share on other sites
snk_kid    1312
Quote:
Original post by evanofsky
Okay, I tried using an std::vector, and it still doesn't work:

for(int i = 0; i < num_objects; i++) {
Object* object;
Init_Object(&object);
list.push_back(object);
}

list[i]->DoSomething(); // crashes


Is that how the code exactly is?

if so, then first thing i should warn you in standard C++ variables declared in a for loop init bit are local to that scope, its not visible beyond it. VC++ 6.0 allows it but its not the correct standard behaviour.

Secondly "i" is outside the bounds of your array there.

if not perhaps posting the exact bit of code and maybe the definition of Init_Object

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
This thread may help you out:

http://www.gamedev.net/community/forums/topic.asp?topic_id=318745

I posted a working example of a 3d array and a 3d vector there, and there are also some great comments in other posts.

David

Share this post


Link to post
Share on other sites
snk_kid    1312
Quote:
Original post by Anonymous Poster
I posted a working example of a 3d array and a 3d vector there, and there are also some great comments in other posts.


Erm his not trying to make any kind of multidimensional array.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
Quote:
Original post by snk_kid
Erm his not trying to make any kind of multidimensional array.


But if he understands that example, he will understand pointers MUCH better.

David

Share this post


Link to post
Share on other sites
Gink    100
Use the iterators if you want to go through a vector

vector<type>::iterator start = vectorObject.begin();
vector<type>::iterator end = vectorObject.end();

while(start != end){
cout << *start << endl;
start++;
}
start is a pointer to the first object in the vector, and end is 1 past the last object stored in the vector

Share this post


Link to post
Share on other sites
Oxyacetylene    426
Quote:
Original post by evanofsky
Okay, I tried using an std::vector, and it still doesn't work:

for(int i = 0; i < num_objects; i++) {
Object* object;
Init_Object(&object);
list.push_back(object);
}

list[i]->DoSomething(); // crashes



Does Init_Object take an Object*, or an Object**?

If it takes an Object*, then Init_Object(&object) is wrong. &object, is the address of the pointer, not the address stored in the pointer.

Remember Object*, is a pointer. Object** is a pointer to a pointer.

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