Array of Objects in C++

Tekkan
Unregistered
 
Post: #1
Ive been having problems simply creating an array of pointers to objects in C++.

If for example, I had created the class "point" (with a constructor that takes 3 arguments, x,y,z), I figured that something like this would create an array of triangles

Code:
point* array_point = new point[10](0, 0, 0);

this doesn't work. I get the error that C++ forbids initializing objects with the keyword "new". And I get even more errors if I try to create the array without calling the constructor, like this:

Code:
point* array_point = new point[10];

How do I fix this? Thanks in advance.
Quote this message in a reply
Member
Posts: 254
Joined: 2005.10
Post: #2
I think you have to statically create the array then fill each cell with pointers. Like so...

Code:
point*[10] points;
for(int i = 0; i<10; i++)
{
    points[i] = new point(0, 0, 0);
}

...or something like that anyway. You could always encapsulate the code into some kind of function to get it down to 'one line'.
Quote this message in a reply
Sage
Posts: 1,066
Joined: 2004.07
Post: #3
Well if you don't mind mixing in some C code, allocating an array in C looks like this:

Code:
#include <stdlib.h>

point* points = (point*)malloc(sizeof(point) * 10); //where 10 is the size of the array

//then initialize all the points in your array
int i = 0;
for (i = 0; i < 10; i++)
   points[i] = new point(0, 0, 0);

Or you could go without having a pointer to the array and just do

Code:
point points[10];

int i = 0;
for (i = 0; i < 10; i++)
   points[i] = point(0, 0, 0);

As for the true C++ way, I'm not terribly sure. Sorry.
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #4
You definitely don't want to be using malloc in a C++ program until you're very certain of what you're doing. It can cause very subtle bugs.

I suspect what the OP wanted was

Code:
class point
{
    float _x, _y, _z;
public:
    point(float x, float y, float z) : _x(x), _y(y), _z(z) {}
    point() : _x(0.0f), _y(0.0f), _z(0.0f) {}
};

// ....

point *array = new point[10];

But if not, then BlackTiger's is pretty close (should be point *array[10]).
Quote this message in a reply
Moderator
Posts: 702
Joined: 2002.04
Post: #5
OneSadCookie Wrote:You definitely don't want to be using malloc in a C++ program until you're very certain of what you're doing. It can cause very subtle bugs.

Care to elaborate? I tend to use malloc() in C++ a lot (very similar to Nick's technique), and I've only ever encountered one oddity (the difference between malloc()'ing and new()'ing a struct which contained objects, not object pointers - oops Blush)

Mark Bishop
--
Student and freelance OS X & iOS developer
Quote this message in a reply
Moderator
Posts: 1,140
Joined: 2005.07
Post: #6
As long as you're consistent where you only delete a newed pointer or free a malloced pointer, it doesn't matter. If you mix and match them, then you may run into problems. (for example, new[] and delete[] offset the pointers when you allocate arrays of objects) Though honestly, the only time you should ever need to use malloc/free are if you were to use some C functions (such as strdup) which allocate using malloc or want to use the realloc function. If you want to allocate an array of objects without calling the constructor, you can just call new with a char array of the size you want and cast it to the object pointer type. (just remember to call delete[] with it as a char *)

If you want to call a custom constructor on an uninitialized object array, you could simply overload operator new like so:
Code:
void *operator new(size_t size, void *p)
{
   return p;
}
This is called a placement new, since it calls new from the same point in memory, which essentially just calls the constructor. If you take all my suggestions, you could then do something like this:
Code:
point *array_point = (point *)new char[10*sizeof(point)];
for (unsigned int i = 0; i < 10; ++i)
   new (array_point + i) point(0, 0, 0)
This is with the overloaded operator new as shown above inserted somewhere in your code. When you delete, you will have to typecast the pointer to a char * like so.
Code:
delete[] (char *)array_point;

edit: oh, and Nick, I don't think you wanted to call new in your loop. Rasp I'm assuming you meant to do an assignment like with your statically allocated array. (though having a placement new, like I showed above, should improve performance a bit since it doesn't have to copy any data or call operator=)
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #7
The issue is that malloc doesn't call constructors, and free doesn't call destructors. If you're sure you're not hitting that case, then it's OK to use them. If you're a beginner, it's easier to use new, new[], delete and delete[] for everything.

Another thing to watch for: new must be matched by delete, and new[] by delete[]; if they're not matched this way the behavior is undefined. For MSVC, "undefined" means "crash", so that's relatively straightforward; for GCC, "undefined" means "delete on a new[]d array doesn't call enough destructors", which is much more subtle.
Quote this message in a reply
Moderator
Posts: 702
Joined: 2002.04
Post: #8
akb825, OneSadCookie: thanks for that; yeah, I know not to mix new/delete with malloc()/free(), and that malloc() doesn't invoke constructors/free() doesn't invoke destructors; I just wondered if there were any other issues of which I was unaware (there usually are Rasp)

Mark Bishop
--
Student and freelance OS X & iOS developer
Quote this message in a reply
Moderator
Posts: 1,140
Joined: 2005.07
Post: #9
Actually, I forgot: my method doesn't call destructors as well. However, you can call the destructor manually in a loop if you want. (just call array_point[i].~point()) For very simple objects (such as that point), it isn't necessary.
Quote this message in a reply
Member
Posts: 63
Joined: 2005.12
Post: #10
Unless I missed it, the option of using containers from the SC++L hasn't been mentioned yet. This is almost certainly the easiest and safest option, and will make most if not all array-related operations that you might want to perform much more straightforward.

In your case, you would most likely want to use std::vector. A quick example:

Code:
// Your original code:
point* array_point = new point[10](0, 0, 0); // Compile error, or course

// And, you of course have to remember to delete 'array_point' at some point!

// With std::vector, this becomes:
std::vector<point> array_point(10, point(0, 0, 0));

// Which creates a dynamically resizable array of 10 points, each
// initialized to (0, 0, 0).

// By using the algorithms from the SC++L, you can streamline many other
// operations as well. For example, resetting all of the points in the array
// to (0, 0, 0) can be written as:
std::fill(array_point.begin(), array_point.end(), point(0, 0, 0));

// You can also resize the array at any time, more or less, if you find you
// need more or fewer points than originally anticipated.

Also, on the subject of malloc vs. new, IMHO it's best to avoid the use of malloc/free in C++ programs (mostly for the aforementioned reason that they only work with PODs). Also, with proper use of RAII containers where appropriate, it shouldn't be necessary to use new/delete directly that often either.
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  mutable array - fill with objects - draw to view burrows111 2 2,774 Apr 21, 2010 02:32 PM
Last Post: burrows111
  memcpy(stuct array pointer struct array point) unknown 22 11,385 Sep 29, 2005 03:16 PM
Last Post: unknown