Constructing Pointer to Array of Classes

So I was making my large program, and it has a pointer with dynamically allocated memory for an array of 8 classes(for now). The class that's being pointed to has my own constructor, not a default constructor. I was searching for how to do this earlier, but couldn't find a direct answer to it. All I found was on using the default constructors with pointers to classes. Those links are here:
http://www.fredosaurus.com/notes-cpp/oop-condestructors/constructors.html
http://cplusplus.com/doc/tutorial/classes/

So... Here's basically what my code looks like!
1
2
3
4
5
6
7
8
9
int main()
{
	int stuff;
	int x=8;
	Category *store;
	store=new store[x];
	for(int m=0;m<x;m++)
		store[m]->(stuff);
}

I haven't tried building it yet and am afraid to because it's really big and I know that I'll have lots of bugs to go through. So I came here and am asking...

Can anyone affirm that the store[m]->(stuff) line would work after just allocating the space for the store variable of class type Category? Or would I have to pass all the data I wanted to pass with the constructor with a set method instead?

Thanks!
1
2
3
std::vector<Category> store;
store.reserve(8);
store.push_back( Category(params) ); //it will use the copy constructor to create the object in the container 


store[m] is not a pointer
I don't think I made myself entirely clear in my first post...

I'm going to be reading the number of type "Category" classes I want to make from a file (so an array wouldn't work, which was why I was going with dynamically allocated data). Each of those categories will have different data in them, all read from this same file. The program won't actually need to be changing the data inside of the "Category" class, which is why I wanted to do it in the constructor, because it just made the most sense.

EDITING...

And no offense ne555, thank you for the reply, but you basically pasted three lines of code explaining what one of those lines of text do... I have no idea what your snippet does, or how to use it. You didn't even give me a link or anything further explaining the concept behind what you wrote.

Any other input?
Last edited on
First, the line of code:

store = new store[x];

should be:

store = new Category[x];

What are you trying to do with this line of code?

store[m]->(stuff);

Is this supposed to be a call to your constructor? If it is, this is not at all the way to do it.

Not withstanding my confusion, I'll try to offer some useful information:

First to be clear: a default constructor is a constructor that either has no parameters, or if it has parameters, all the parameters have default values. So just because you've written "your own" constructor, doesn't mean that the constructor you've written isn't a "default" constructor. If you've written NO constructor for your class (default or otherwise), then the compiler will create a default constructor for you. This compiler-generated constructor takes no arguments, has an empty constructor initializer list and an empty body.

For the following, I'm assuming you have indeed written a constructor that is NOT a default constructor.

When an array of objects is instantiated either on the heap via a call to operator new (as you have done) or on the stack; the default constructor is called for each object in the array. If you've written a non-default constructor for your class and have NOT written a default constructor for your class, then the compiler won't generate a default constructor for you and you're going to end up with a compile error for your call to operator new. You MUST have a default constructor if you intend to create your array of objects this way. Furthermore, if you do create a default constructor for your class (so that your call to new Category[x] compiles) then when this call returns all of your objects will be constructed already; and it's a no-no to invoke a constructor on an object that's already been constructed.

You have a few choices:

1) Use a default constructor followed up by setter methods.

2) Allocate an array of pointers to stores, and then allocating a single store at a time:

1
2
3
Category **store = new Category*[x];
for(int m=0;m<x;m++)
    store[m] = new Category(stuff);


Then of course the syntax to, say, invoke a method f() on an object in your array becomes: store[i]->f() instead of store[i].f().

3) Use placement new. This involves a slightly cumbersome process of first allocating a chunk of memory big enough to hold your array and then using operator PLACEMENT new to invoke your non-default constructor for each object in your array. Likewise, the cleanup process requires the two steps of first making an explicit call to the destructor for each object in your array and then deleting the memory. This article I found explains this nicely:

http://www.devx.com/cplus/10MinuteSolution/30508/1954

4) Use a vector as suggested by ne555 above.

I hope this helps,
Matt
Last edited on
Thank you option #2 is what I wanted! Yes I wrote my own constructor which takes in parameters, and each of those in the array of pointers to stores have different data to be inputted. So stuff would actually be an array in my case, and I'd be calling store[m] = new Category(stuff[m]); to construct each of the stores.

My question is answered now!
Last edited on
I have a small setback; how do I delete those Categories afterwards? I got it running and everything, but when I try deleting each member of the "store" variable, my program crashes. And when I try deleting "store" by itself, it doesn't free the real bulk of the memory.

So I assume that this is what you're supposed to do...
1
2
3
4
5
6
7
8
9
10
11
12
13
int stuff; // Pseudocode representing a number of stuff that will be passed in
int x=8;
Category **store=new *Category[x];
for(int m=0;m<x;m++)
	store[m]=new Category(stuff);
	// store has now been inialized, and is used in this area......

/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

	// finished with using store, now to remove it
for(int i=0; i < x; i++)
	delete []store[i];	// Crashes at this point
delete []store;	// Without the line above, nothing inside "store" is really deleted 


And for some background info, this is an example of what the Category class looks like and what I'm trying to do...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
class Category
{
private:
	Subcat **store;	// A similar class, shown below
	string name;
	int size;
public:
	Category(int a,string b, int *x, string *y, string**z)
	{
		size=a;
		name=b;
		store=new *Subcat[a];
		for(int i=0; i < a; i++)
			store[i]=new Subcat(x[i],y[i],z[i]);
	}
	~Category()
	{
		for(int i=0; i<size; i++)
			delete []store[i];
		delete []store;
	}
};

class Subcat
{
private:
	string *store;
	string name;
	int size;
public:
	Subcat(int a, string b, string *c)
	{
		size=a;
		name=b;
		store=new *string[a];
		for(int i=0; i < a; i++)
			store[i]=c[i];
	}
	~Subcat()
	{
		delete []store;
	}
};


Is there anything you see wrong with my code? Or is there something else I'm supposed to do to in the destructor methods?
Last edited on
if you allocate with new you delete with delete
if you allocate with new [] you delete with delete []

Also there is the danger of a double delete. You will need to provide a copy constructor and an assigment operator that will copy the "objects" (depth copy) and no just the pointers (shallow copy).
So since I allocated with new *Category[] the first time, and next new Category(stuff) for each individual one, do I simply delete with this?
1
2
3
for(int i=0; i < x; i++)
	delete store[i];
delete []store;


Also, I'm not really sure if I follow what you mean with the copy constructor and assignment operator. How does that have to do with deleting the allocated memory? If you mean that if I want to make a second identical category, by doing something like store=storeB; and then later on trying to delete both will cause problems, then I'm totally good there.
Last edited on
...copy constructor and assignment operator.How does that have to do with deleting the allocated memory?


copy constructor makes shore that new "copied" object will be allocated with their own memory space, same does assignment operator... he will alocate new memory space for lvalue.
otherwise both operand would point to the same memory space.

1
2
3
for(int i=0; i < x; i++) //I think you should use ++i instead
	delete store[i];
delete []store;


cheers.
If you mean that if I want to make a second identical category, by doing something like store=storeB; and then later on trying to delete both will cause problems, then I'm totally good there.
Yes. ┬┐how is that you are guarded against that?
Oh by saying I'm totally good there, I mean I understand the implications of that. Also in my program, I don't ever make any statements like that, so I won't have to worry about that, and yeah that basically isn't an issue that I'm looking to solve :D

Thanks for your replies though, I appreciate it!
Topic archived. No new replies allowed.