methinks i don't understand pointers

Started by
13 comments, last by Oxyacetylene 18 years, 10 months ago
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));
   }

   list[random_number]->DoSomething();
}
Suppose hypothetically that it crashes when I call DoSomething(). I'm probably doing something embarassingly wrong; please enlighten me!
Advertisement
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 = new Object()      InitObject(list);   }   list[random_number]->DoSomething();}
Thanks a bunch! Except, what happens if "Object" is abstract and you can't create instances of it?
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));   }   list[random_number].DoSomething();}

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().
"We should have a great fewer disputes in the world if words were taken for what they are, the signs of our ideas only, and not for things themselves." - John Locke
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);
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.
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->DoSomething(); // crashes
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->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
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

This topic is closed to new replies.

Advertisement