Author : Glen McCluskey & Associates LLC
Page : << Previous 2 Next >>
// copy a string
};
// constructor
Copy::Copy()
{
ln = 0;
maxln = 0;
vec = 0;
freelen = 0;
freestr = 0;
}
// destructor
Copy::~Copy()
{
int i;
// delete buffers
for (i = 0; i < ln; i++)
delete vec[i];
// delete vector itself
if (vec)
delete vec;
}
// copy a string char* Copy::copy(char* s) {
int i;
char** newvec;
int len;
char* p;
assert(s && *s);
len = strlen(s) + 1;
// first time or current buffer exhausted?
if (len > freelen) {
if (!vec || ln == maxln) {
// reallocate vector
maxln = (maxln ? maxln * 2 : COPY_VEC);
newvec = new char*[maxln];
assert(newvec);
for (i = 0; i < ln; i++)
newvec[i] = vec[i];
if (vec)
delete vec;
vec = newvec;
}
// allocate new buffer
vec[ln] = new char[COPY_BUF];
assert(vec[ln]);
freelen = COPY_BUF;
freestr = vec[ln];
ln++;
}
// allocate and copy string
freelen -= len;
p = freestr;
freestr += len;
strcpy(p, s);
return p;
}
#ifdef DRIVER
#include <stdio.h>
#include <alloc.h>
main() {
long cl;
const int MAXLINE = 256;
char buf[MAXLINE];
FILE* fp;
char* s;
#ifdef USE_COPY
Copy co;
#endif
cl = coreleft();
fp = fopen("c:/src/words", "r");
assert(fp);
while (fgets(buf, MAXLINE, fp) != NULL) {
#ifdef USE_COPY
s = co.copy(buf);
#else
s = new char[strlen(buf) + 1];
assert(s);
strcpy(s, buf);
#endif
}
fclose(fp);
printf("memory used = %ld\n", cl - coreleft());
return 0;
}
#endif
Hidden Constructor/Destructor Costs
Consider a short example of C++ code:
class A {
int x, y, z;
public:
A();
};
class B {
A a;
public:
B() {}
};
A::A() {x = 0; y = 0; z = 0;}
Class A has a constructor A::A(), used to initialize three of the class's data members. Class B has a constructor declared inline (defined in the body of the class declaration). The constructor is empty.
Suppose that we use a lot of B class objects in a program. Each object must be constructed, but we know that the constructor function body is empty. So will there be a performance issue?
The answer is possibly "yes", because the constructor body really is NOT empty, but contains a call to A::A() to construct the A object that is part of the B class. Direct constructor calls are not used in C++, but conceptually we could think of B's constructor as containing this code:
B::B() {a.A::A();} // construct "a" object in B class
There's nothing sneaky about this way of doing things; it falls directly out of the language definition. But in complex cases, such as ones involving multiple levels of inheritance, a seemingly empty constructor or destructor can in fact contain a large amount of processing.
Declaration Statements
Suppose that you have a function to compute factorials (1 x 2 x ... N):
double fact(int n)
{
double f = 1.0;
int i;
for (i = 2; i <= n; i++)
f *= (double)i;
return f;
}
and you need to use this factorial function to initialize a constant in another function, after doing some preliminary checks on the function parameters to ensure that all are greater than zero. In C you can approach this a couple of ways. In the first, you would say:
/* return -1 on error, else 0 */
int f(int a, int b)
Page : << Previous 2 Next >>