6

When a TForm is created in Builder (or Delphi) code is added to main to create these forms at application launch:

Application->CreateForm( __classid( TxForm), &xForm );

this makes things easier, but is it wise when the applications has 10, 20, 50, 100 forms? I am assuming that this can grab all kinds of memory and system handles. The form can always be created on the fly when needed by removing it using the Project->Options->Forms dialog and:

std::auto_ptr< TxForm > myForm( new TxForm( this ));

myForm->ShowModal();

So the question is, which is better, to let C++ Builder do it its own way, or to manually create the form when required?

Gregor Brandt
  • 7,659
  • 38
  • 59
  • 1
    Of course, you can make Delphi not autocreate the forms in question by removing them from the list of autocreate forms at Project >> Options >> Forms. You probably already know that but I thought it should be mentioned with the question. – Muhammad Alkarouri Nov 10 '10 at 20:57
  • Correct, I will add that to the question for clarity. – Gregor Brandt Nov 10 '10 at 21:10

5 Answers5

5

It really depends of how you use the forms in your application. I usually create them on the fly when needed and then free them when I'm done. It's more manual work but saves resources (and costs a little bit of CPU every time which can cause delays).

If you rarely use a form, I'd say create/free(delete) manually when needed but if you use the form all the time and for the whole life of the app, stay with the default way.

AlexV
  • 22,658
  • 18
  • 85
  • 122
5

Suggesting to let the IDE "do it its own way" implies that the IDE is employing some kind of intelligence to the way it generates code for creating forms and data modules. It isn't. It's just creating what you told it to create, and in the order you told it to use. If you didn't explicitly tell it what to do via the project-options dialog, then it's just creating things in the order you added them to your project. The IDE does not know any better than you do.

Using auto-created forms and data modules encourages the use of the global variables that the IDE declares for you to refer to those objects. You don't need them.

Auto-create only your main form. When you need anything else, create it yourself using the typical way of creating objects: Call the constructor, and store references to the objects in local variables or fields of your other objects, not the IDE-provided globals, which you should delete. Don't bother with CreateForm. I wrote an article explaining why.

Rob Kennedy
  • 161,384
  • 21
  • 275
  • 467
2

Forms that are created but not yet visible take memory and make impact startup time but shouldn't use any system handles, since stuff like window handles aren't allocated until the window is actually shown.

With that said, I almost always create forms manually (using code similar to your auto_ptr), because I can't stand having global variables. Creating forms manually gives a few advantages: faster application startup, forms are always displayed in a known good state, and easier to switch later to showing multiple instances of a form at once if you need to.

As the VCL documentation explains, deleteing a form directly (or indirectly, by using a stock std::auto_ptr) may cause memory errors, since the form may have unprocessed messages. To avoid this problem, I wrote two smart pointer classes that takes care of calling Release instead of delete. You can download them from http://gist.github.com/671452.

Josh Kelley
  • 56,064
  • 19
  • 146
  • 246
  • 2
    Why does your DeleteOrRelease() call delete at all. According to the docs Release will do the job every time? – Gregor Brandt Nov 10 '10 at 21:07
  • 1
    If you look at the source code for Release, it calls `PostMessage(Handle, ...)`, and reading the value of the Handle property calls HandleNeeded, which allocates a handle (i.e., allocates a bunch of Windows resources needed to show the form on screen). It seems silly to me, for a form that was never shown or whose window handle has since been destroyed, to allocate a handle just so you can immediately release it. Calling delete if !HandleAllocated is a micro-optimization, but it's never caused me any problems. – Josh Kelley Nov 10 '10 at 22:57
  • 4
    If you read the VCL documentation more closely, it says: "**Any event handlers for the form or its children** should use Release instead of Free (Delphi) or delete (C++). Failing to do so can cause a memory access error." An **event handler** for the form needs to use Release() instead of Free() or delete, but any other code not called from within the context of the form's event handlers can safely use Free() or delete without worrying about "memory errors". – Remy Lebeau Nov 11 '10 at 01:11
  • The same document, as linked above, also has this explicit line: **Use Release to destroy the form and free its associated memory.** So, we still have to use Release, but not because of possible memory errors? – Gregor Brandt Nov 11 '10 at 01:47
  • @Remy: Thanks for the clarification. I've actually had event handler chains that end up in a form being released from its own event handler, so I'll probably continue using Release in my own code. – Josh Kelley Nov 11 '10 at 04:04
  • @gbrandt: No, Remy's explanation is fine as is. Use Release if it's from an event handler, delete is safe otherwise. – Josh Kelley Nov 12 '10 at 21:47
  • And how to you figure that? The documentation is VERY clear in a single sentence in a single paragraph. Later it says that release is required to free event handlers, but it never says a delete is if there are no event handlers. – Gregor Brandt Nov 15 '10 at 17:00
  • @gbrandt: From Remy's comment. From reading the source. From experimentation. From reading the documentation. ("Use Release to do this" is telling you why you want to would use Release, not every other possible way of accomplishing the same purpose.) – Josh Kelley Nov 15 '10 at 17:22
  • Agreed. The documentation is VERY clear that Release() is only required if deleting the form from inside an event handler. It says as much. – Remy Lebeau Nov 19 '10 at 02:47
2

IMO, auto-creating forms that you probably won't use, such as the About box, is just wasteful. I usually auto-create the main form, and then dynamically create the rest, as-needed.

Chris Thornton
  • 15,620
  • 5
  • 37
  • 62
0

Unless the application is just a VERY SMALL test bed or POC, create just the main form (and/or an global datamodule if it's your style/design) and create all others manually.

Creating all forms on loading is just a waste and (depending of what is done on forms) can make your program load fast as a sea turtle walking on the sand...

Fabricio Araujo
  • 3,810
  • 3
  • 28
  • 43