Question regarding the Main Component Tutorial

#1

I apologize in advance for a noob C++ question, but I would appreciate a quick answer.

Hi everyone,
I’m just learning JUCE (and C++) and I have some questions after completing the “The main component” tutorial. The tutorial exercise was to change the background color of the window everytime the window was resized. I found 2 working solutions using the Random class, but I’ve got a feeling that I’m not handling this right.

1st Solution:

class MainComponent : public Component
{
	//...
	Random* myRandomFloat = new Random();
};

void MainComponent::paint (Graphics& g)
{
	//...
	g.fillAll(Colour::fromFloatRGBA(myRandomFloat->nextFloat(), 0.0, 0.0, 0.0));
}

MainComponent::~MainComponent()
{
	randomFloat->~Random();
}

Q1: If I don’t call the destructor for myRandomFloat manually, I get an object leak exception. Is calling the destructor the correct way to go about it?

2nd Solution:

class MainComponent : public Component
{
	//...
	Random myRandomFloat;
};

void MainComponent::paint (Graphics& g)
{
	//...
	g.fillAll(Colour::fromFloatRGBA(myRandomFloat.nextFloat(), 0.0, 0.0, 0.0));
}
	
MainComponent::~MainComponent()
{
}

Q2: Why does this even work, even though I did not use a constructor for the Random object?
Q3: Why does this not give any leaks compared to the 1st Variant?

I suspect both of these are poor solutions, so I would really appreciate if someone could tell me how it’s done right.

0 Likes

#2

The second solution is the correct one. You don’t need to call the constructor manually because in that case it is enough you just declare the object as your class member and the default constructor of the object will be used. Also, when you use a class as a value like that, the destructor is also automatically called when the owning object is destroyed. This is always the best way to do things, but it’s not always possible to do things like that and you may need to work with objects via pointers. When you need to do that, you should always try to find a way to use a “smart” pointer instead of using raw pointers.

Also note that you should almost never do the manual class destructor call like randomFloat->;~Random();. If you really must deal with raw pointers and delete their pointed to object manually, use the delete call like delete randomFloat;

(The manual class destructor call is used in very rare scenarios where the object was manually constructed in some memory location you yourself decided. When you use “new”, the memory location usually comes from the runtime/OS and you should use the C++ delete operator which both deallocates the memory and calls the class destructor.)

1 Like

#3

If you’re not already familiar with the concept of heap vs stack allocation, you should look into that for a bit more information about what’s going on here.

Your first solution allocates the object on the heap (because you use the new keyword), so it must be manually deleted before your program terminates or else it leaks. As @Xenakios mentions, you can use ‘smart pointer’ types like std::unique_ptr and they will manage the memory lifetime for you. You just create the pointer, and once it goes out of scope, the object is automatically cleaned up. In modern C++, you should really avoid typing new and delete, and use the appropriate smart pointer type for your use case.

Your second solution allocates the object on the stack. Objects created on the stack are automatically deleted when they go out of scope, so you don’t have to worry about new/delete or using smart pointer types. Generally speaking, you should declare everything on the stack unless you have a reason not to.

1 Like