Making an array with non-default constructors(C++)

Started by
8 comments, last by PrestoChung 13 years, 11 months ago
When I make my array like this:

Sector** secPointer;
secPointer = new Sector *[size2nplus1]; 
for ( int i = 0; i < size2nplus1; ++i )
	secPointer = new Sector[size2nplus1];
I can't access a member in my Sector class without crashing and I think it's because Sector only has a constructor with 2 parameters:
Sector::Sector(int setid, World& theWorld)
Everything else seems okay to be accessed within the Sectors, except this array:

float** hMap;
hMap = new float *[theWorld.secsize];	// ** ~ 2 dimensional array
for (int i = 0; i < theWorld.secsize; ++i )
	hMap = new float[theWorld.secsize];

for (int i = 0; i < theWorld.secsize; i++)	{
	for (int j = 0; j < theWorld.secsize; j++)	{
		hMap[j] = 0;
	}
}
So you can see I can't have this code in a default constructor with no arguments, because the Sector needs to know the size of the hMap array to use based on the secsize of theWorld argument (theWorld.secsize).
Advertisement
Quote:Original post by PrestoChung
So you can see I can't have this code in a default constructor with no arguments, because the Sector needs to know the size of the hMap array to use based on the secsize of theWorld argument (theWorld.secsize).

Yes indeed. The default constructors do not do what you need: you should make them private.

Use a std::vector to contain your data and construct them explicitly with the appropriate arguments.

Stephen M. Webb
Professional Free Software Developer

Speed of access to the hMap array is critical, as it will be accessed many times every frame so I did not want to use std::vector. Because theWorld.secsize does not change during runtime, I may be able to use a fixed size, it will just be inconvenient if I choose to change the size in the future (I guess not so bad, I just have to change 2 extra numbers.)
..and of course the errors if I don't change the size in all 3 places
The simple solution is to write a default constructor that initialize those values to something that you want and write mutator to set their value.
Quote:Original post by PrestoChung
Speed of access to the hMap array is critical, as it will be accessed many times every frame so I did not want to use std::vector. Because theWorld.secsize does not change during runtime

The fact that std::vector can grow dynamically does NOT imply an efficiency penalty when reading from it.
Though if using MSVC, you may get an efficiency penalty reading from it unless you disable the secure SCL functionality.
Quote:Original post by PrestoChung
Speed of access to the hMap array is critical, as it will be accessed many times every frame so I did not want to use std::vector.


That's fine; the vector won't make it any slower to access the memory if you're not resizing it. It will just sit there with, under the hood, a pointer to a single chunk of memory, just the same as the one you would allocate and manage yourself. It's just a more organized way of doing it: the supporting code to deallocate the memory, set up the initial objects (by taking a single "prototype" object and copying it for each element) etc. is already written for you.

However, for a rectangular, 2-dimensional array, you should instead consider boost::multi_array. Making a vector of vectors will cost something in terms of efficiency - and so does your current approach - because each "row" is allocated separately. That means you waste memory for the pointers to rows and can lose performance because of the rows being spread out across the memory space instead of being in a single chunk. The boost::multi_array container is designed to allocate a single chunk but make it behave like a statically-allocated, multi-dimensional array. (It does this by also remembering the dynamic size of each dimension of the array, and using those numbers to do math to index into the storage - plus a bunch of other neat magic that is very difficult to do yourself. How difficult, you say? Well, I tried a few years ago to reproduce the basics of it, and while I had a pretty solid idea of how, I got bored and gave up. ;) )
Quote:Speed of access to the hMap array is critical, as it will be accessed many times every frame so I did not want to use std::vector.
Do you have any evidence that accessing a std::vector is slower than accessing a raw array? Or is that just a guess on your part?

(As noted previously, runtime iterator and range checking can cause some standard library containers to appear to be 'slow' when in debug mode, so be sure you're testing a release build with iterator debugging turned off. With MSVC, for example, _HAS_ITERATOR_DEBUGGING and _SECURE_SCL should both be set to 0.)
It was actually a guess on my part.

Thanks for the advice all.

Unfortunately my program is choking on the number of operations needed to update all the maps however (around 9 million i think at current settings, not every frame, but the program is freezing up when i launch it) so i'm going to have to move this up into the Zone class and make it parallel my LOD function to reduce the number of calculations.

This topic is closed to new replies.

Advertisement