1

I have to use an array of pointers to Objects and I must also pass it as parameter to methods. However the way to do this eludes me. Here is the method I use for the initialization of the elements of the array. When I dereference them in main, their data are not correct (they contain memory addresses). What is the correct way? Might it be false the way I dereference them?

void createSquares(Square* squareArray[]){

    PropertySquare PropertySquare1(1,"purple",120);
    PropertySquare PropertySquare2(2,"purple",170);

    squareArray[1] = &PropertySquare1;
    squareArray[2] = &PropertySquare2;
.
.
.
}

In main:

Square *allSquares[22] ;
createSquares(allSquares);

cout<<"ID is: "<<allSquares[1]->getID()<<endl;
cin.get();

As I said the ID is finally a memory address.


Update based on answers:

I have tried this and it does not work as well.It is imperative for me to use polymorphism.

vector<Square*> allSquares;
createSquares(allSquares);

void createSquares(vector<Square*> &squares){

PropertySquare PropertySquare1(1,"purple",120);
PropertySquare PropertySquare2(2,"purple",170);

squares.push_back(&PropertySquare1);
squares.push_back(&PropertySquare2);

}

in main:

for (vector<Square*>::iterator it=allSquares.begin(); it!=allSquares.end();it++){
   it->
}

It does not allow me to use the virtual functions of Square since it is abstract. Any suggestion?

1
  • 1
    Best to pick up a good C++ book and learn about object lifetimes! Commented Nov 27, 2011 at 16:49

3 Answers 3

3

Everything you're doing is Not Good. It's tricky to figure out where to begin, so let me start at the end and present The Right Way:

typedef std::unique_ptr<Square> square_ptr;

void createSquares(std::vector<square_ptr> & v)
{
  v.emplace_back(new PropertySquare1(1,"purple",120));
  v.emplace_back(new PropertySquare1(2,"green",370));
  // ...
}

int main()
{
  std::vector<square_ptr> allSquares;
  createSquares(allSquares);

  for (const auto & p : allSquares)
    std::cout << "ID is: " << p->getID() << std::endl;
}

Now to break down your problems:

First off, you are storing the pointers of local variables. Those local variables die at the end of the function scope, and the pointers become dangling. Dereferencing is a program error.

Second, to fix this, you should create dynamic objects: squareArray[1] = new PropertySquare1(1,"purple",120); However, that is problematic, too. Someone will have to clean up those objects! You could iterate over the array and call delete on each element.

Third, 22 is a "magic number" (because it's neither 0 nor 1). This should not be hard-coded. If the number really is a compile-time constant, name it somewhere.

Fourth, either way, don't use raw arrays. Either use a std::array if the size is known at compile-time, or a std::vector if the size is determined at runtime.

Fifth, putting it all together, a dynamic container of smart pointers takes care of all your worries. That's the one presented in my code. The alternative, a static array of smart pointers, wouldn't use an initialization function at all, but rather it'd be initialized right on the spot:

const std::size_t nfuncs = 22;
std::array<square_ptr, nfuncs> allSquares {
  new PropertySquare1(1,"purple",120),
  new PropertySquare1(2,"green",370),
  // ...
};
Sign up to request clarification or add additional context in comments.

4 Comments

You should mention that emplace_back is a new C++11 feature. In C++03, you'd need to use push_back with a copyable type (e.g. boost::shared_ptr because the only smart pointer in C++03, std::auto_ptr, cannot be used in containers). Anyway, std::shared_ptr might even be the right solution in C++11 since there might be the desired to be able to have copies of the pointers in the container (and if not, using pointers instead of values and std::move is probably just unnecessary overhead anyway).
@celtschk: Yeah, so is unique_ptr, range-based for and uniform initialization :-) It's a bit more icky in C++03. I'll leave the shared-vs-unique debate to a later time when the OP has figured out what she wants.
Regarding your second remark: What about if the Objects are ever necessary while the program is running? Should I delete them in its last lines?
@arjacsoh: Well, probably nobody is going to mind if you don't. Just be aware of what you've created, and be conscious of the fact that you kill them during shutdown. Personally I'd always clean up, though, since then you can use memory debuggers and always demand zero errors.
1

What is false is that

PropertySquare PropertySquare1(1,"purple",120);
PropertySquare PropertySquare2(2,"purple",170);

Are destroyed the moment createSquares returns. So your array contains junk when you print those IDs.

Comments

0

Because PropertySquare variables are declared in stack, they will be destroyed once the function returns. You want to declare them in heap instead by

squareArray[1] = new PropertySquare PropertySquare1(1,"purple",120);
squareArray[2] = new PropertySquare PropertySquare1(2,"purple",170);

and delete them in main by calling delete allSquares[1] etc.

1 Comment

I recommend indexing with 0, btw.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.