Even though I am using Visual C++, I confess I’ve have always preferred and used just C features in my windows programming. I have decided to try class objects in a little fractal program I’m working on. I have defined two classes to do the heavy duty calculations that will identify elements of Mandelbrot and Julia sets. A calculation method is called for each pixel in the client area, say 500,000+ times for a typical Window. I have visions of filling up the heap with class objects if I’m not careful. I presume I should try to minimize the number of times a specific class object is generated even though the object will be destroyed when it goes out of scope. Heap memory is still tied up when an object is destroyed until the garbage collector is able to do its work. Right?
As shown in the code snippet below. I have tried declaring these class objects in three different places (a) at the start of the windows procedure, (b) at the start of the WM_PAINI section and (c) inside the two nested ‘for’ loops that calculate the value of an element tied to a pixel. I think the number of times the class objects will be created and destroyed will be minimized if I declare them at the start of the WM_PAINT procedure. (All three options work fine.)
At the start of the window procedure per se, objects will be created and destroyed when any message is handled, not just the WM_PAINT messages. Inside the nested ‘for’ loops, the objects would be created and destroyed for each pixel in the client area—say 500,000 times.
What do you think? Have I made the right choice?
This program is designed to generate fractal maps for either the Mandel or the Julia sets but not both at the same time. I will probably add at least one more type. ( The user will be able to select which type to produce with a menu or a dialog box.) I assume there is no fundamental reason not generate all objects types even though only one will be used. The compiler seems to have trouble handling declarations in any kind of selection of alternates option( if…else, switch, etc). Comments?
I am beginning to conclude that I should just go back to a C-type calculation function for each type and give up on the objects. Comments?
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
( data section left out)
//MandelbrotSet objectMandelbrot(maxI); Decided not declare here. New objects
//JuliaSet objectJulia(jReal,jImag,maxI); would be generated for every message
double FractalX, FractalY;
MandelbrotSet objectMandelbrot(maxI); //Decided to declare here New objects
JuliaSet objectJulia(jReal,jImag,maxI);// are generated only if WM_PAINT message is being handled
hdc = BeginPaint(hWnd, &ps);
// MandelbrotSet objectMandelbrot(maxI); Decided not to declare here New objects
//JuliaSet objectJulia(jReal,jImag,maxI); would be generated for every pixel.
//determines if elements are in the Mandelbrot set
//determines if elements are in the Julia set
if(i==maxI) SetPixel(hdc,x,y,RGB(160,50,75));//these elements are in the set
SetPixel(hdc,x,y,Color[i % nColors]); //these elements are not in the set
Heap memory is still tied up when an object is destroyed until the garbage collector is able to do its work. Right?
No. There is no garbage collector in C++. Heap memory is freed as soon as you free it.
However if you are allocating and freeing lots of very small objects very frequently, you might suffer from memory fragmentation, which can appear like a memory leak.
You are wise to do minimal work inside the WM_PAINT handler. In fact, I would argue you should even do less than you currently are.
WM_PAINT can be called several times per second (if, for instance, you drag something window over the window to obstruct its view). In your case, every time it's called, it is rebuilding the fractal image. This is a big waste.
What would be better is if you keep an off-screen DC with a bitmap that has the fractal image already drawn. Then in WM_PAINT simply blit that dc to the display in one BitBlt call. Very quick. Very minimal.
Also, SetPixel is incredibly slow. If you are going to use the offscreen DC, look into CreateDIBSection. It allows you to create a bitmap where you can access pixels as it you were dealing with a large array. Very fast to do pixel-level access.
Thank you, Disch, for a thoughtful reply. It looks like you edited your initial response and made it much more useful to me.
I have many refinements in mind for the program including generating a bitmap and sending it to the screen with bitblt. Also I will include a provision for saving any striking images as .bmp files. Whether to use a GDI or a DIB bitmap hinges on whether I let the user let his own color options.