Topic: Novice questions


Author: Adl@debug.cuc.ab.ca
Date: Tue, 18 Jan 1994 06:56:43 GMT
Raw View
I am a C++ novice and have some basic questions that I'm hoping some kind
soul can answer ...

-----

Q1:  I know that I can't combine new/malloc and delete/free calls, but can
I use them independently?  i.e. use new/delete for my objects, say, and
malloc/free for a char array.

-----

Q2:  I'm a bit confused about what happens during ctor/dtor calls.  I
thought that I could use a dtor to free any memory allocated by my object
anywhere within the class; but after reading through some discussions it
looks like I use the dtor to free ONLY that memory created in the ctor,
and that any memory created in other methods gets freed automatically when
the object is freed.

As an example,

class myClass {

   char *name;

   myClass();
   ~myClass();

   setName(char *newName);

}

If I initialize name to NULL in the constructor, but later change it in
setName() (which does some kind of malloc thing), should I free the memory
occupied by name within my dtor, or does it get freed automatically since
I didn't create that memory in my ctor?  Sorry for the redundancy :)

-----

Q3:  I understand this business with virtual functions, but what good does
a virtual dtor really do?  Doesn't the dtor for a subclass get called
regardless of whether it's virtual or not?  Does it have something to do
with order?

-----

Many thanks in advance...





Author: Adl@debug.cuc.ab.ca
Date: 19 Jan 94 03:44:06 +0600
Raw View
Date: Tue, 18 Jan 1994 06:56:43 GMT
Message-ID: <1994Jan18.065643.26722@debug.cuc.ab.ca>
Lines: 47

I am a C++ novice and have some basic questions that I'm hoping some kind
soul can answer ...

-----

Q1:  I know that I can't combine new/malloc and delete/free calls, but can
I use them independently?  i.e. use new/delete for my objects, say, and
malloc/free for a char array.

-----

Q2:  I'm a bit confused about what happens during ctor/dtor calls.  I
thought that I could use a dtor to free any memory allocated by my object
anywhere within the class; but after reading through some discussions it
looks like I use the dtor to free ONLY that memory created in the ctor,
and that any memory created in other methods gets freed automatically when
the object is freed.

As an example,

class myClass {

   char *name;

   myClass();
   ~myClass();

   setName(char *newName);

}

If I initialize name to NULL in the constructor, but later change it in
setName() (which does some kind of malloc thing), should I free the memory
occupied by name within my dtor, or does it get freed automatically since
I didn't create that memory in my ctor?  Sorry for the redundancy :)

-----

Q3:  I understand this business with virtual functions, but what good does
a virtual dtor really do?  Doesn't the dtor for a subclass get called
regardless of whether it's virtual or not?  Does it have something to do
with order?

-----

Many thanks in advance...





Author: daniels@biles.com (Brad Daniels)
Date: Wed, 19 Jan 1994 15:47:24 GMT
Raw View
In article <1994Jan18.065643.26722@debug.cuc.ab.ca>,
 <Adl@debug.cuc.ab.ca> wrote:
>Q1:  I know that I can't combine new/malloc and delete/free calls, but can
>I use them independently?  i.e. use new/delete for my objects, say, and
>malloc/free for a char array.

Yes.  I don't know whether it's guaranteed to work in all implementations,
but it has to work in order for C++ to interoperate with C properly.

>Q2:  I'm a bit confused about what happens during ctor/dtor calls.  I
>thought that I could use a dtor to free any memory allocated by my object
>anywhere within the class; but after reading through some discussions it
>looks like I use the dtor to free ONLY that memory created in the ctor,
>and that any memory created in other methods gets freed automatically when
>the object is freed.

You're probably reading more into somebody's comments than they intended.
The storage associated with the object itself goes away after the destructor
executes, but any memory the object allocated dynamically stays around until
somebody deletes it.  This means that the dtor must explicitly delete any
objects and free any malloc'ed memory the object allocates unless you want
it to stay around forever.

>Q3:  I understand this business with virtual functions, but what good does
>a virtual dtor really do?  Doesn't the dtor for a subclass get called
>regardless of whether it's virtual or not?  Does it have something to do
>with order?

It's needed if you delete a pointer to an object where the actual object
is of a subclass of the pointer's type.  E.g.:

class base {
    char *p;
  public:
    base() { p = new char[100]; }
    ~base() { delete [] p; }
};

class sub: public base {
    char *p2;
  public:
    sub() { p2 = new char[100]; }
    ~sub() { delete [] p2; }
};

main() {

    base *ptr = new sub;
    delete ptr;

}


In the above program, I'm putting a pointer to an object of type sub into
a pointer to base, then deleting the base object.  Since the dtor is not
virtual, only the ~base() dtor gets called, meaning that sub::p2 never
gets freed.  If the dtor were virtual, deleting ptr would end up calling
~sub() through the virtual call mechanism, and all would be well.

BTW - this group is for standards discussions.  You want comp.lang.c++.
I've redirected followups there.

- Brad
------------------------------------------------------------------------
+ Brad Daniels                  | "Let others praise ancient times;    +
+ Biles and Associates          |  I am glad I was born in these."     +
+ These are my views, not B&A's |           - Ovid (43 B.C. - 17 A.D.) +
------------------------------------------------------------------------




Author: robina@wv.mentorg.com (Robin Albrecht)
Date: Thu, 20 Jan 1994 04:06:26 GMT
Raw View
(Note that this is followed up in comp.lang.c++, as these questions
don't directly relate to the standard.)

Disclaimer (since I usually get some minor point wrong): This response is
offered in the spirit of being helpful in answering the questioner's
questions, and is not even trying to be 100% correct about every point.

In article <1994Jan18.065643.26722@debug.cuc.ab.ca>, Adl@debug.cuc.ab.ca writes:
|> I am a C++ novice and have some basic questions that I'm hoping some kind
|> soul can answer ...
|>
|> -----
|>
|> Q1:  I know that I can't combine new/malloc and delete/free calls, but can
|> I use them independently?  i.e. use new/delete for my objects, say, and
|> malloc/free for a char array.

Yes, though many people will tell you to "use C++ if you're using C++".
E.g.

 char *p = new char[n];
 delete [] p; //  don't forget the "[]" when deleting arrays!


|> -----
|>
|> Q2:  I'm a bit confused about what happens during ctor/dtor calls.  I
|> thought that I could use a dtor to free any memory allocated by my object
|> anywhere within the class; but after reading through some discussions it
|> looks like I use the dtor to free ONLY that memory created in the ctor,
|> and that any memory created in other methods gets freed automatically when
|> the object is freed.

Yikes!  *What* discussions have you been reading? :-)

|> As an example,
|>
|> class myClass {
|>
|>    char *name;
|>
|>    myClass();
|>    ~myClass();
|>
|>    setName(char *newName);
|>
|> }
|>
|> If I initialize name to NULL in the constructor, but later change it in
|> setName() (which does some kind of malloc thing), should I free the memory
|> occupied by name within my dtor, or does it get freed automatically since
|> I didn't create that memory in my ctor?  Sorry for the redundancy :)

Destructors do not automatically free any memory, no matter where it was
allocated.

Just in case you're not aware of this... Having ownership of memory transfer
between objects can be very problematic.  Rather than having set_name() take
control of memory allocated elsewhere, it would be far better to have it
make a copy of the string into newly allocated storage -- storage it owns.
If you think that an extra string copy is too expensive, you may want to do
some timing tests; unless this is something you do an *awful* lot, it is
extremely unlikely that the extra copy will be noticeable (and the time spend
debugging problems introduced by having unclear ownership can be spent in
tuning other parts of the program).  If you can't make one class responsible
for both allocation and deallocation, you'd better have a darned good
policy for how those strings get allocated and deallocated!

|> -----
|>
|> Q3:  I understand this business with virtual functions, but what good does
|> a virtual dtor really do?  Doesn't the dtor for a subclass get called
|> regardless of whether it's virtual or not?  Does it have something to do
|> with order?

No, the dtor for the subclass doesn't get called regardless of whether the
dtor is virtual or not.  Consider this (untested) code:

class Base {
 Base::Base() {}
 Base::~Base() {}
};

class Derived : public Base {
 Derived::Derived() {}
 Derived::~Derived() {}
};


foo()
{
 Base *p = new Derived;
 delete p; //  calls Base::~Base()

 Derived *q = new Derived;
 delete q; //  calls Derived::~Derived() (which calls Base::~Base())
}

Without a virtual destructor, how does 'delete p' know to call the destructor
for Derived?  Answer: It doesn't.  (Okay, maybe in this case it could because
all the code is in one place, but what about less contrived cases?)

If Base's destructor is virtual, you get the right behavior.

(Note, however, that the situation is more complicated you've got a pointer to
an array rather than a single object...)

|>
|> -----
|>
|> Many thanks in advance...
|>

--
Robin Albrecht
Mentor Graphics, IC Division
Email: robin_albrecht@mentorg.com