[comp.os.msdos.programmer] Borland Turbo C++ bugs/problems/features

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