I’ve recently started to try to use Juce’s Array and HeapBlock to avoid using new and delete, which was my MO until I read some disparaging comments by Jules. This is the first time I’ve made a lot of use of smart pointers and the like in C++, so I have some questions about using them properly…
When using an Array as a class member to hold instances of another class, the only way I’ve gotten it to work was to make an Array<TheClassName*> classArray. Then, when populating the array, do classArray.add( new TheClassName() );. Is this the best way to do it? Will the Array delete those news appropriately when the class for which it’s a member is destructed? To give context, one place I’m doing this is in an AudioProcessor where the same effect is being applied to all channels. So, I’ve created a class (Processor) which does the processing, and the AudioProcessor has a class member (processors) which is an Array of these processor classes. The first time prepareToPlay is called, I do
for ( int n = 0; n < getNumInputChannels(); n++ )
processors.add( new Processor() );
Is this smart or woefully misinformed?
I used to use a lot of raw pointer arrays in my processing… so the Processor above would have, say, a class member float* someBuffer, and in the Processor constructor, there would be someBuffer = new float[numSamples]; and in the destructor there would be a delete someBuffer. So, in the spirit of getting rid of new/delete, I first tried using an Array instead. But, I found that there huge increase in CPU (maybe fivefold) due to all of the calls to Array’s  operator, which checks the index based on the array bounds in addition to just being more expensive than a raw array access (among other things). So, I tried buffer.getRawDataPointer()[index], which also had a lot of overhead, and then I tried switching to a HeapBlock, which still had (less) overhead… finally I have arrived at using HeapBlocks, but having a class member both for the HeapBlock AND the HeapBlock’s raw data pointer. So I have something like
and then when I want to access a member of window I do window[n]. This has removed virtually all of the overhead but it looks pretty ugly and I can’t imagine it’s the best practice…
When I’m using a HeapBlock as I was just describing, will it take care of freeing itself? Eg, if I allocate in the class constructor do I need to free in the destructor, just like new/delete or is it smart enough to free itself? Same question for Arrays, after .add()ing a bunch of stuff.
Sorry for the long-winded post, it’s been a fun experience learning this stuff and I think I’m getting closer and closer to writing some nice code. Thanks in advance for any thoughts.
OK - great. Would you say that the technique I’m using (an Array or OwnedArray of pointers to a class, populated with new’s) is sane?
Well, I was finding that using the  operator on the HeapBlock actually did have some overhead… eg
int nSamples = 1024;
samples.allocate( nSamples, false );
float* samplesRaw = samples.getData();
for (int n = 0; n < nSamples; n++)
// This calls the HeapBlock  operator, which then retrieves the float in memory and returns it
samples[n] = 1.0;
// This just retrieves the float in memory - no call to another function.
samplesRaw[n] = 1.0;
The additional per-sample call to the  operator function was doubling CPU usage in my case… I’m fairly positive. Something else could be going on - but switching from HeapBlock  operator dropped CPU significantly. Is this reasonable at all?
3) Heapblock is just for blocks of raw memory - it uses malloc and free, so you can’t use it for arrays of objects that have constructors or destructors.[/quote]
Sorry, I don’t think I was clear, here’s what I mean:
samples.allocate( 1000, true );
feet.add( 1.0 )
// Do I need to call free here?
// Do I need to call clear here?
…in a debug build, that’s reasonable, but I’d be astounded if any modern C++ compiler would fail to inline such a simple method in a release build!
Re: calling free() - no, there’s no need: the HeapBlock’s destructor will free the memory automatically. That’s the whole point, really… if it didn’t do that, there’s be no reason for the class to exist!. As long as you delete the HeapBlock, it’s impossible for it to leak memory.
…in a debug build, that’s reasonable, but I’d be astounded if any modern C++ compiler would fail to inline such a simple method in a release build![/quote]
Ah, that makes sense, that must have been it.
Re: calling free() - no, there’s no need: the HeapBlock’s destructor will free the memory automatically. That’s the whole point, really… if it didn’t do that, there’s be no reason for the class to exist!. As long as you delete the HeapBlock, it’s impossible for it to leak memory.[/quote]
OK, that’s what I figured, and that definitely makes sense - just wanted to make sure I wasn’t misunderstanding the usage and leaking memory inadvertently…