toma@tekgvs.LABS.TEK.COM (Tom Almy) (07/28/90)
I have found several bugs in the Turbo C++ tutorial that make me believe this was really a rush job (or they don't know how to write C++ programs.) But there are several performance issues of (Turbo) C++ that should be mentioned. It has already been pointed out that Turbo C++ is slower compiling a C program that Turbo C V2.0. But the problem gets worse with C++ programs (the larger header files are mostly to blame). Executables are bigger as well. For instance, compare hello.c with hello.cpp: C C++ Compile time: 2 sec 3.8 sec Executable size: 6074 17852 (The c program does printf("Hello world"), while the c++ program does cout << "Hello world". The calc program example from the Stroustrup book (with addition of trig functions) compiles to a 35440 byte file, while the same program rewritten in JPI Modula-2 (don't ask) is 11510. (The source file in C++ is 60% the size, though!). ============================ But to the meat of the bugs. I've always been concerned about dynamic storage management problems in C++, which the destructor functions sort of address. But the Borland tutorial writer can't get it correct! In program listdemo.cpp, the quantity of free memory is reported before and after running the bulk of the program (which demonstrates dynamic lists and constructor/descructor operation). But the numbers aren't the same! The problem is in the constructor function for Lists, which creates the list head. A list object consists of just one item, a pointer to a node. But the definition of the constructor is: List::List () { Node *N; N = new Node; N->Item = NULL; N->Next = NULL; Nodes = NULL; // sets node pointer to "empty" // because nothing in list yet } Note that the constructor generates a Node, which it initializes and then ignores. Since N is a Node* rather than a Node, the Node doesn't get deleted. But the whole thing is stupid. This function works correctly and doesn't leave the garbage around: List::List () { Nodes = NULL; // sets node pointer to "empty" // because nothing in list yet } and it is in better agreement with the comment! ======================= The second problem, actually a pair of problems, occurs in xstring.cpp. The String class has two elements, a pointer to char, char_ptr, and an integer, length. A descructor is defined to delete the character string (which is fine). The program overloads the + operator to do a string concatenation in the line: CString = AString + BString; The example in the book (which is corrected on the disk) modifies This to hold the concatenated string. Of course this doesn't work because This is AString, and thus AString gets modified as a side effect. But the example does have an unfortunate side effect, it wastes the creation of a String. The function: String String::operator+ (String& Arg) { String Temp( length + Arg.length ); strcpy(Temp.char_ptr, char_ptr); strcat(Temp.char_ptr, Arg.char_ptr); return Temp; } Since the scope of Temp is the function, the return Temp command uses the constructor to build a copy of Temp (which gets returned) and then the String destructor is called to delete Temp. I guess this is correct operation, but it surely is inefficient, and I can't figure out a way around it. The biggest problems is the lack of a String class overload of the = operator. The standard C++ (and C) assignment operation occurs, copying the temporary into CString, element by element. Unfortunately this wipes out the string that was already assigned to AString, and it can never be reclaimed. The fix is to write: String &String::operator= (String& Arg) { delete char_ptr; length = Arg.length; char_ptr = new char [length + 1]; strcpy(char_ptr,Arg.char_ptr); return *this; } perhaps there is a cleaner way of doing this. It is interesting to note that the implicit assignment to temporary variables needed when evaluating expressions works just fine, with destructors being called as necessary. It's just the explicit assignment that needs the overloaded operator (Can any C++ experts explain this???) Tom Almy toma@tekgvs.labs.tek.com Standard Disclaimers Apply