Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
C++ For Dummies (2004) [eng].pdf
Скачиваний:
84
Добавлен:
16.08.2013
Размер:
8.09 Mб
Скачать

386 Part VI: The Part of Tens

Checking Use Syntax Highlighting tells the editor to color words within your program to indicate their type. The editor flags comment lines with one color, keywords such as switch another, variable names yet another, and so on. The myriad of colors is a little nauseating at first, but it’s very useful once you get used to it. You can change the colors used, but I don’t see much point in doing so.

The Auto Indent feature is intended to be a labor saving device: The editor tabs the cursor over the “appropriate” column when you press Return. Normally, the appropriate column is the same as the previous line that isn’t a comment or blank. The cursor automatically indents after an open brace. Unfortunately, it doesn’t unindent upon seeing a close brace (nothing’s perfect). Backspace Unindents is a related and corresponding setting.

I deselected Use Tab Character. This forces the editor to use spaces, and spaces only, to position the cursor. I did this primarily because I cut and pasted programs from Dev-C++ into my word processor when writing this book.

The Highlight matching braces/parenthesis setting has a serious implication that gets its own Top 10 listing.

Highlight Matching Braces/Parentheses

The Highlight matching braces/parenthesis setting appears in the Editor Options window that is accessible from the Tools menu. When set, the Dev- C++ editor looks for the corresponding opening brace whenever you enter a closed brace. In addition, when you select either an open or closed brace, Dev-C++ changes the corresponding brace to Bold. The same rules apply for parentheses.

This feature helps you keep your braces matched. You can easily forget a closed brace when you’re entering your program. It’s just as easy to get the braces screwed up when editing your program.

There is, however, a serious downside when using Dev-C++ Version 4.9.8.0: You can’t open a module in which there are more open braces than closed braces. It seems that the editor scans your .cpp file when you open it to figure out which closed brace goes with which open brace. The editor hangs up if it runs out of program before it finds enough closed braces.

Thus, if Dev-C++ appears to just go away when you open your C++ source code module, try the following:

1.Kill Dev-C++ — it’s not going to return anyway. Press Control-Alt-Delete. Select the Task Manager option. Select Dev-C++ from the list of active programs that appear. Finally, select End Task.

Chapter 30: The Ten Most Important Optional Features of Dev-C++ 387

2.Start Dev-C++ from the Start menu without a file.

3.Uncheck the Highlight matching flag.

4.Open your file.

If that doesn’t work, punt and download the most recent version from the

www.bloodshed.net Web site, because something is wrong.

Enable Exception Handling

Exception handling is the flexible error handling mechanism discussed in Chapter 25. Choose Tools Compiler Options. Select the Settings tab. Work your way through the tree of compiler options in the left window until you find Code Generation. Make sure that the Enable exception handling flag is set to Yes — the default for this setting is No.

Adding exception handling code makes your program slightly larger and slightly slower. However, that’s a small price to pay for the exception error handling mechanism. See Chapter 25 if you don’t believe me.

Include Debugging Information (Sometimes)

The Generate debugging information flag is also one of the compiler options. Choose Tools Compiler Options. Select the Settings tab. Click Linker in the options tree. The Generate debugging information flag should be set to Yes during the debug process. The debugger doesn’t work if this flag isn’t set. In addition, Dev-C++ has only limited information to fall back on if your program crashes.

When the debugging flag is set to Yes, Dev-C++ includes the location within the program of every label and every line of code. (That’s how the debugger knows where to set breakpoints.) Even lines of code from library routines, code that you didn’t write, are included. All this location information can add up. This information adds to the executable file.

I compiled one of my programs first with the debug flag turned on and a second time with it turned off. The executable was a whopping 1.2MB. The same program generated a 440K executable file.

The moral is: Be sure that the Generate debugging information flag is acti­ vated during the entire development period, but clear the flag for the final release version.

388 Part VI: The Part of Tens

Create a Project File

You can generate a program from a single .cpp file without using a project file. This is fine for small programs. However, you should break larger pro­ grams into smaller modules that can be understood more easily. Building multiple .cpp modules into a single program requires a Project file. I describe this in Chapter 22.

Customize the Help Menu

Dev-C++’s help default topics are limited to the compiler, and don’t include the C++ language or any of its libraries. Fortunately, Dev-C++ allows you cus­ tomize the Help options. You can add files in Microsoft Help (.hlp) and Compiled HTML (.chm) formats to Help. (Note: You’ll have to find extra .hlp and .chm files. You can find these on the Web if you look hard enough. Neither Dev-C++ nor www.bloodshed.net provide an extra Help file.)

As an example, I downloaded the freely available Help file Win32.hlp. This file lists the Windows operating system Application Program Interface (API) calls. Choose Help Customize Help Menu to access the Help Menu Editor.

Click the Add button along the top of the window. Dev-C++ opens a browse window. Navigate to the help file that you want to add. Select the file and click OK. Finally, check the appropriate boxes at the bottom of the window. Here I included the Win32.hlp file in the Help search. Click OK. The contents of the new help file are now available from the Help menu.

You can add as many help files as you like.

Reset Breakpoints after Editing the File

Dev-C++ sets breakpoints based on line number. Unfortunately, it does not move the breakpoint when a line is inserted or removed from the source file. For example, suppose that I set a breakpoint on line 10 within my program. If I then add a comment between lines 9 and 10, the breakpoint now points to the comment. Obviously, comments are not executed, so the breakpoint becomes meaningless.

Remember to recheck your breakpoints to be sure they still make sense after you edit the .cpp source file.

Chapter 30: The Ten Most Important Optional Features of Dev-C++ 389

Avoid Illegal Filenames

Dev-C++ isn’t very good at identifying illegal filenames. Rather than generat­ ing a meaningful message (such as maybe, “Illegal Filename”), the compiler generates a string of misleading error messages.

Dev-C++ can’t handle filenames that contain spaces. The filename My Program.cpp is not allowed. Nor can it handle folder names containing spaces. The filename C:\My Folder\MyProgram.cpp is not legal either.

Dev-C++ can handle network files, but the Console window cannot. Thus, you can compile the program \\Randy\MyFolder\MyProgram.cpp, but you can’t debug resulting executable. In addition, the program executes normally at first but generates some obscure operating system error message before it completes.

Include #include Files in Your Project

C++ allows you to collect statements into separate files that you can #include in multiple source files. C++ puts no restrictions on the type of things that you can put in an include file. However, you should put only the following types of statements in an include file:

Function prototypes

Class definitions

Template definitions of all types

Definition of all global variables

You should not include executable statements (except for functions within the class definition itself) in an include file. Remember to add the include file­ name to the project list, even though it contains no source code. Doing so tells Dev-C++ to rebuild the C++ source whenever an include file changes.

Executing the Profiler

You shouldn’t be overly concerned with how fast your program will run when you’re writing. (By this, I’m not suggesting that you do really stupid things that take up lots of computer time.) It’s hard enough to write a working pro­ gram without worrying about writing tricky “efficient” C++ code statements. In addition, it’s an odd fact that, if you ask a programmer where she spends most of her programming time, she’s almost always wrong!

390 Part VI: The Part of Tens

But what if your program is too slow and you want to spiff it up? Fortunately, Dev-C++ (and most other C++ environments) offers something known as a profiler. This nifty little tool watches your program to determine where it’s spending its time. Once you know that, you can decide where to spend your valuable coding time.

To enable Profiling, I chose Tools Compiler Options. Then I selected Settings and Code profiling to set Generate Profiling Info for Analysis.

I then added the following edited version of the DeepCopy program from

Chapter 18:

//

// DeepCopy - provide a program to profile

//

#include <cstdio> #include <cstdlib> #include <iostream> #include <strings.h>

#include <profile.h> using namespace std;

class Person

{

public: Person(char *pN)

{

pName = new char[strlen(pN) + 1]; if (pName != 0)

{

strcpy(pName, pN);

}

}

Person(Person& p)

{

pName = new char[strlen(p.pName) + 1]; if (pName != 0)

{

strcpy(pName, p.pName);

}

}

~Person()

{

if (pName != 0)

{

delete pName; pName = 0;

}

}

Chapter 30: The Ten Most Important Optional Features of Dev-C++ 391

char *pName;

};

void fn1(Person& p)

{

//create a new object

//Person* p1 = new Person(p.pName); Person p1(p);

}

void fn2(Person p)

{

// create a new object Person* p1 = new Person(p); delete p1;

}

int main(int nNumberofArgs, char* pszArgs[])

{

Person p(“This_is_a_very_long_name”);

for(int i = 0; i < 1000000; i++)

{

fn1(p);

fn2(p);

}

return 0;

}

This program does nothing more than call fn1() and fn2() millions of times — you can’t get an accurate picture of a program that executes in less than one second. That’s okay because you don’t need to worry about making a program that executes in a second or two any faster anyway. Adding the loop causes the program to take a few seconds to complete.

In addition, I removed the output statements. You quickly discover that output is a very slow process. The time spent outputting information to the screen would have swamped everything else.

When executed, the program opened a Console window for a few minutes and then closed the window. Not very exciting so far. I then selected Execute Profile Analysis. The window shown in Figure 30-1 appeared.

392 Part VI: The Part of Tens

Figure 30-1:

A profile analysis shows you where a program is spending its time.

Interpreting a profile takes a certain amount of practice. This window shows the functions invoked during the execution of the program (there may be other functions in the program, but they were never called). The first column lists the names of the function followed by the percentage of time spent in that function in the second column. In this case, just more than 24 percent of the program’s execution time was spent in the copy constructor Person::Person(Person&). The Self Secs column refers to the total amount of time spent within the func­ tion — an entire 0.14 second was spent in the copy constructor (almost onefifth of a second — shocking!).

Does this mean that the copy constructor is the slowest function in the pro­ gram? Not necessarily. In reality, the program spent more time in this func­ tion because it was called more often than any other — the copy constructor is invoked from both fn1() and fn2().

Skipping down to these two functions, you can see that fn2() took more time than fn1(). In fact, fn2() took twice as much time as fn1() — 0.04 second versus 0.02 second. fn1() creates a new copy of the Person object passed to it. However, fn1() receives its argument by reference from main().

By comparison, main() passes the Person object to fn2() by value. This causes C++ to invoke the copy constructor. The fn2() function then makes a copy of the copy. Finally, fn2() creates the copy from heap memory using the new keyword. Allocating memory off the heap takes a certain amount of time.