Learning C++ Memory Management

C

Curt Welch

I could use some help. After 35 some odd years as a C programmer, I've
decided it's finally time to learn C++. I've got a year+ experience with
Smalltalk and about a year of experience with Java as well as experience
with Objective C, so all the OO concepts or the mechanics of C I know very
well. But what I'm having trouble figuring out is the details of what the
C++ language does for you, and what it doesn't do for you, with all the
complexities of memory management.

I'm talking a class on C++ at my local community college, which is working
well at it's intended purpose of motivating me to actually put the time in
to learn the langauge, but it's not working well at actually teaching me
anything because I'm way ahead of the class (I think I might know C and C++
better than the teacher). Though it's a second semester class listed as
"Advanced C++", it's really just "Beginning Programming in C++ - class II"
as he's still going basic concepts like pointers and what a class is.

I'm the type of guy that is not happy unless I understand all the nuts and
bolts of the language. If I don't know the langauge well enough to write a
compiler for, the I don't feel like I know it well enough to use it. :) I
certainly don't know the C++ features well enough to do that yet.

I'm trying to understand what the C++ compiler will do for you, and not do
for you, in terms of calling constructors and destruction so you can be
sure when you write code that our not creating memory leaks, or dangling
pointers, or all the other problems that can show up. First, I thought you
had do it all yourself, like with straight C, but that would use new and
delete. But then I learned new and delete was only if you wanted to
manipulate pointers but that you could use local object variables and it
would do it for you. Then I thought object variables were actually
implemented as pointers (like Java) where C++ would do the new and delete
for you behind the scene. But then I figured out it was just straight C
struct semantics and the local objects were just being allocated on the
stack, and all C++ was was doing for you was a hidden calls to constructors
and destructors. That seemed cool. So I was thinking the trend was not to
use object pointers and new or delete unless you needed dynamic structures.
It seemed that if you just used object variables, C++ would make sure your
destructors and constructs were always correctly called.

But then I found out that when using call by value and assignment, C++
didn't take care of things for you after all. So if you have objects that
need special care, you have to supply the copy constructor and overide the
assigment operator to make sure things are done right.

So, I'm getting there. But I'm still somewhat lost becuase the books I'm
reading don't explain what the C++ compiler is doing for you behind the
scene. They show by simple examples how to write the assignment operator,
but they don't explain what the default assignment operator does for
example.

To really understand what's going on here, I need to know what's happening
behind the scene, and that's what I've not found documented anywhere yet.

So the first real question to the group, is where do find this out? Is
there a good FAQ, or web site, or books, you can recommend that will
concisely and simply give me _all_ the facts I need to know about these
sorts of things - especially one that's intended for an advanced programmer
to quickly pick up what the compiler is really doing for you (thinks like
"making a function virutal means it's added to the structure as a function
pointer and all calls the the virtual function are indirected though the
function lookup table in the object").

I did find this web page last night which was very good (but really only a
start and not all the answers I need), I'd like to see more like this on
the rest of the language...

The Anatomy of the Assignment Operator

http://icu-project.org/docs/papers/cpp_report/the_anatomy_of_the_assignment_operator.html

A lot of these sorts of things I figure out on my own by writing lots of
short test programs and doing a lot of reverse engineering work - but
that's very timing consuming and I was hoping someone could recommend some
good material to read.

And example of a simple specific I don't yet understand how how something
like string works (and when it won't work).

If I have a simple class:

Class Person
{
string name;
int age;
};

And using it as local automatic variables:

Person a, b;

And write something like:

a = b;

What happens? Have I just created a memory leak with the string or will
that work? I don't know how the string class is implemented (yet), so I
can't guess what it's doing. And I don't know what the C compiler does by
default for assignment like the above, so I don't even know if it's
possible for the string class to do the right thing and not create a memory
leak.

If I wrote a class like the Person example above, do I need to overload the
assignment operator to make it work correctly? And how do I write the
assignment operator to make it work?

Does the default assignment operator just do the same thing as struct
assignment in C? That is, just do a raw byte copy of the struct from b to
a in the above without any calls to constructors or destructors? And, if
it does that, is the string class implemented in some way that prevents
that type of assignment from creating a memory leak (I'd guess it would
have to implement its own memory management and do it's own garbage
collection if that was the case - which doesn't sound reasonable).

Or does it generate a default version of the assignment operator for every
class which will do a member by member assignment - which would then call
the string object assignment operator function to "do the right thing" for
the string? In which case the assignment of the Person class objects would
not create a memory leak or any other problem and it work work?

And in general, if I create a class like the Person one above and use any
object in it, will it work as long as assignment of all the members is
correctly supported by all the member objects?

And if you use use object pointers instead of objects in your class and
allocated the objects in your constructor with new, is default assignment
guaranteed not to work if the pointers have owner responsibility for the
memory pointed to becuase pointer assignment will always by default just
assign pointer A to pointer B without any help from the C++ compiler doing
calls to destructors and copy constructors or object assignment functions
for you?

And, how do I find out how string is implemented? When you do an
assignment, does it make copies of the strings, or used shared strings with
reference counts? Are they mutable? Or is it a reference count with
shared objects (like java objects), or does it us a copy on write strategy
to make assignment fast but make then act as if the strings had been copied
no assignment?

The above is typical of the type of thing I'm trying to work through
currently.

Some of this may be in the books I already have, but it's going to take
some time to get though them. The book for the class is the 2" thick
Deitel "C++ How to Program" book which is ok, but very verbose for someone
like myself which is an experienced C programmer just trying to pick up
intimate details of the C++ extensions to C. I can read an entire chapter
of that book and learn only 3 things that could have been communicated in
one paragraph. I also have an old C++ book (been sitting in my self for
decades) which assumes the reader already knows C, which is more to my
speed, but it still fails to talk about what's really happening behind the
scene so I can figure out the answers for myself to questions like the
above, and it is so old for example it seems to be pre-template support in
C++ so I need something similar but more up to date.

Any answers to the above questions and pointers to recommended books or
other material you think would best fit what I need to learn would be
greatly appreciated....
 
C

Curt Welch

Victor Bazarov said:
Curt said:
I could use some help. After 35 some odd years as a C programmer, I've
decided it's finally time to learn C++. [..]

I'm the type of guy that is not happy unless I understand all the nuts
and bolts of the language. [..]

I'm trying to understand what the C++ compiler will do for you, and not
do for you, in terms of calling constructors and destruction so you can
be sure when you write code that our not creating memory leaks, or
dangling pointers, or all the other problems that can show up. [..]

So the first real question to the group, is where do find this out?

Start with TC++PL (Special Edition is the latest and fullest), then
probably move to "Inside C++ Object Model" (IIRC). The latter delves
much deeper into the inner workings of the language/compiler/environment
than a "regular guy" would need to start with C++.
Is
there a good FAQ, or web site, or books, you can recommend that will
concisely and simply give me _all_ the facts I need to know about these
sorts of things - especially one that's intended for an advanced
programmer to quickly pick up what the compiler is really doing for you
(thinks like "making a function virutal means it's added to the
structure as a function pointer and all calls the the virtual function
are indirected though the function lookup table in the object").

I did find this web page last night which was very good (but really
only a start and not all the answers I need), I'd like to see more like
this on the rest of the language...

The Anatomy of the Assignment Operator

http://icu-project.org/docs/papers/cpp_report/the_anatomy_of_the_assi
gnment_operator.html

A lot of these sorts of things I figure out on my own by writing lots
of short test programs and doing a lot of reverse engineering work -
but that's very timing consuming and I was hoping someone could
recommend some good material to read.

And example of a simple specific I don't yet understand how how
something like string works (and when it won't work).

If I have a simple class:

Class Person

class Person

Just shows how much more practice I need that I didn't just spot that
error!
std::string name;

Yeah, the old book doesn't cover all that name space stuff, still got to
get that figured out...
int age;
};

And using it as local automatic variables:

Person a, b;

And write something like:

a = b;

What happens?

Member-wise assignment. Essentially,

a.name = b.name;
a.age = b.age;
Have I just created a memory leak with the string or will
that work?

No leak.
I don't know how the string class is implemented (yet), so I
can't guess what it's doing.

Whatever it's implemented to be doing. If you're using standard library
facilities like that, you should be OK.
And I don't know what the C compiler does by
default for assignment like the above, so I don't even know if it's
possible for the string class to do the right thing and not create a
memory leak.

If I wrote a class like the Person example above, do I need to overload
the assignment operator to make it work correctly?
No.

And how do I write the
assignment operator to make it work?

If you want to, you just declare

Person& operator=(const Person&);

in the class, et cetera. TC++PL should be able to unveil/explain most
of those things to you.
Does the default assignment operator just do the same thing as struct
assignment in C?

Mmm... No. It does more.
That is, just do a raw byte copy of the struct from b to
a in the above without any calls to constructors or destructors?

Definitely not.

Get TC++PL and maybe "Accelerated C++" by Koenig and Moo, and you're
going to be set until you read and comprehend those books (it might take
you a few months).

V

Great, thanks, I'll look into that.

And of course, right after posting, I found answers to half my questions in
the next 4 pages of the old book I was reading! Yeah, I now see that
default copy and assignment works as if you had done member by member copy
or assignment so it uses the Object's overloaded versions of those
functions if needed allowing a lot of stuff to work correctly for you. But
now I understand why it's working and how. One more little step
forward....

The old book I have is "Programming in C++ by Dewhurst and Stark" (first
edition - 1989). But after I posted, I noticed another C++ book on my
shelf which is the second addition of that same book (1995) which is a
little more up to date. They both are written assuming the reader already
knows C so that's good for me. I was most the way though the older of the
two, so now I need to start over and read the newer and them move on to the
more advanced (I've got a few decades of C++ langauge development to catch
up with here. - might take me a few more weeks... ).

Thanks for the recommendations....
 
I

Ian Collins

Curt said:
The old book I have is "Programming in C++ by Dewhurst and Stark" (first
edition - 1989). But after I posted, I noticed another C++ book on my
shelf which is the second addition of that same book (1995) which is a
little more up to date. They both are written assuming the reader already
knows C so that's good for me. I was most the way though the older of the
two, so now I need to start over and read the newer and them move on to the
more advanced (I've got a few decades of C++ langauge development to catch
up with here. - might take me a few more weeks... ).
1995 still predates the standard.

Forget those and follow Victor's advice ("Start with TC++PL (Special
Edition is the latest and fullest)").
 
C

Curt Welch

Jeff Schwab said:
That's extremely non-trivial. Modern C++ compilers are remarkable
pieces of technology. For a philosophical intro, see:

http://www.research.att.com/~bs/siblings_short.pdf


You should almost never have problems of that nature. Some of the
regulars in this group will suggest that you use a Java-style garbage
collector with C++ (yes, you can), but I recommend against it. One term
you'll hear a lot is RAII, which I find solves most resource-management
problems gracefully and predictably.


Memberwise assignment. The default copy constructor performs memberwise
copy. (Really, it's "subobjectwise" since it includes base objects, but
people refer to it as memberwise.)


Since you already have a lot of experience, you may be able to start
with The C++ Programming Language, by Bjarne Stroustrup. Another
oft-recommended text is Accelerated C++, by Andrew Koenig and Barbara
Moo; it may be too beginner-oriented for you, but it's short.

Once you get the basics of construction, destruction, overloading, etc.
understood, you'll have a decent grasp of C++ as it was practiced until
about ten years ago. After that, read The C++ Standard Library, by
Nicolai Josuttis, or the STL Tutorial And Reference Guide, Second
Edition, by Musser, Derge, and Saini. Once you are comfortable writing
simple templates, and using more sophisticated ones, you'll know as much
C++ as many current developers do.

If you're really as interested in the nuts & bolts as you say (and many
of us are), then I recommend C++ Templates, by Vandevoorde and Josuttis,
followed by C++ Template Metaprogramming by Abrahams and Gurtovoy.
These will give you some insight into how C++ is practiced on the ground
today. Modern C++ Design by Andrei Alexandrescu is also very good.


That's almost true, but not quite. :) Usually, each object just gets
one extra pointer, to a separately stored "vtable." The standard
doesn't actually require particular implementations though, just syntax
and behavior. The benefit is that high-level abstractions can be
optimized as the compiler sees fit. This is a bit of a philosophical
difference between C and C++.


That guy's doing everything manually, all in once place. You ordinarily
wouldn't work like that. Those try/catch blocks and delete-statements
are unnecessary if you use decent smart-pointers. (They still happen,
but you shouldn't have to mix them with the main logic.)


The name gets copied, then the age.


That's called bitwise copy. It's what the primitive types do.


Yes, you've got it.


Consult your library implementation's documentation. That's a
particularly non-trivial aspect of a non-trivial standard library.
There are lots of potential implementations, depending on whether the
string supports concurrent access, instance-specific allocators,
copy-on-write, the "short string optimization," etc.


Could be either, depending on the implementation.


Yes, unless they're const.


Usually the latter.


Stay away from old C++ books, unless they're specifically recommended by
somebody who knows what they're talking about. Stay away from the "C++
in 24 seconds" books, too.

Welcome to C++, and good luck!

Thanks a lot for all that. I've got my work cut out for me now...
 
P

pasa

I suggest you read some books to avoid common traps:

Meyers - Effective C++ & More Effective C++
look memory-related Guru of the Week items of Herb Sutter (or in the
Exceptional C++ series)
Sutter-Alexandrescu: C++ Coding standards, following references where
needed
and then the king: Imperfect C++ of Matthew Wilson. There you can get
all the fine corners with workarounds.
Especially the section on RAII/RRID resource management.

The good ways to write copy ctor, op= and destructor is simple: don't
do it. Yeah, there are many books around showing how, or even telling
you must -- those are before RAII and specialised handlers. And
examples likely be not exception safe or failing in some situation.

Certainly you DO write them implementing a RAII handler but it is a
rare case, as for most situation you have them ready in STL or other
libraries.
A lot of these sorts of things I figure out on my own by writing lots of short test programs ...

Forget that. Really. We started that way, found 30% of traps, learned
other 30% traps the hard way, and left the rest as bugs. Good books
list them to read in a few hours. Saving years of headache.
Person a, b;
a = b;
What happens?

It works fine, you get a good copy of b's state in a that shares
nothing. You will not get any leak anyhow.
You use string as member, that handles its op= and destruction closed-
circuit, so it is good to have as member.
Normally you're okay until you don't try to have simple pointer
members. Use smart pointers instead or containers.
I don't know how the string class is implemented (yet),

If it's std::string, it 'handles itself'. As anything else in std::
Does the default assignment operator just do the same thing as struct assignment in C?

Techncally no, semantically yes. In C you get a bitwise copy. In C++
you get a member-wise copy. It would be the same if all members are
builtin types. For struct/class members their operator= is called.
So you can imagine the generated op= as a series of op= calls on all
the base classes and members.
Ctors and dtors are not called.

The std::string's op= nukes the target strings content, allocates
memory to keep the source string's data and copies
it.
It's ctor that takes const char *, allocates memory and copies in the
param.
It's dtor deallocates the memory.

So all your strings that are locals or members will handle all the
memory without you ever having chance to leak, or need to do a single
allocation.
And if you use use object pointers instead of objects ...
Yea, then you have to take all the work.
And, how do I find out how string is implemented?
You don't have to, that's what encapsulation is about. :) Certainly
most compilers have the source, that you can read.
To know the functions and behavior, you have man, MSDN, the standard,
or a good book 'The Standard Library - ... and Reference'
 
J

James Kanze

Curt Welch wrote:

[...]
Mmm... No. It does more.

Yes and no. The semantics of C are such that you can't tell
whether assignment is bit-wise or member-wise. As I understand
it, the standard actually specifies member-wise (as in C++), but
because you can't tell the difference, most compilers do
bit-wise (basically memcpy).

The important distinction in C++ is that you *can* provide an
assignment operator. And in member-wise assignment, it will be
used. So a compiler can only implement assignment (when you
haven't provided it) as a bit-wise copy if none of the
sub-objects has a user defined copy assignment operator. (Which
is, in a certain sense, the same rule as C. Except that in C,
none of the sub-objects will ever have a user defined copy
assignment operator, because such things don't exist.)

To answer the original question precisely: given a statement
like:
a = b ;
the compiler will first determine the types of a and b. If a
has a non-class type, it will then convert b to that type, and
do the assignment (basically, by ensuring that the significant
bits of the converted value end up in the memory of a). If a
has a class type (class, struct or union), the compiler will
construct a list of operator= functions in the class, and do
overload resolution to choose the best one. If the user has not
not declared a copy assignment operator, the compiler will
declare one, and add it to the list. If overload resolution
selects the compiler declared copy assignment operator, the
compiler will then define it. (It's worth noting in this regard
that the standard places enough restrictions on unions to ensure
that bit-wise copy will be indistinguishable from copying the
active member. Because, of course, the standard doesn't require
the compiler to track the active member.)

This is obviously a blatant simplification---the actual rules,
including overload resolution---occupy something like ten pages
in the standard.
Definitely not.

Since the object in question contains an instance of
std::string, which has a user defined copy assignment operator.
(There still won't be any calls to constructors or
destructors---just to the user defined copy assignment
operator.)
Get TC++PL and maybe "Accelerated C++" by Koenig and Moo, and
you're going to be set until you read and comprehend those
books (it might take you a few months).

If he's looking to understand under the hood, I don't think that
the Koenig and Moo will be what he's looking for. Just the
opposite, maybe---they orientation is to get you programming
rapidly and effectively without understanding the underlying
details.
 
J

Jorgen Grahn

I could use some help. After 35 some odd years as a C programmer, I've
decided it's finally time to learn C++. I've got a year+ experience with
Smalltalk and about a year of experience with Java as well as experience
with Objective C, so all the OO concepts or the mechanics of C I know very
well.

But you have learned that those languages handle memory/objects/object
lifetime very differently from C++, I guess.
[...] But then I figured out it was just straight C
struct semantics and the local objects were just being allocated on the
stack, and all C++ was was doing for you was a hidden calls to constructors
and destructors. That seemed cool.

It *is* cool.

....
And example of a simple specific I don't yet understand how how something
like string works (and when it won't work).

If I have a simple class:

Class Person
{
string name;
int age;
};

And using it as local automatic variables:

Person a, b;

And write something like:

a = b;

What happens? Have I just created a memory leak with the string or will
that work? I don't know how the string class is implemented (yet), so I
can't guess what it's doing.

You can assume it Does The Right Thing, no matter how it is implemented.
The way I think about the code above is something like this (modulo
the obvious bugs):

1. Ugh, there is a default constructor which creates Persons with an
empty name and a random (possibly negative) age. I might plug that
hole by

Person(const string& name, int age) { ... }

unless I later find that I need it to be default-constructible.

2. OK, Person doesn't new anything or point to anything it doesn't own.
Thus it is just like any other ordinary object like an int, a
std::string or a struct of ints, or ...

3. I stop worrying and treat Person just as I would treat an int,
except for function calls I pass it by const reference.

/Jorgen
 
Z

ZikO

Curt said:
I could use some help. After 35 some odd years as a C programmer, I've
decided it's finally time to learn C++. I've got a year+ experience with
Smalltalk and about a year of experience with Java as well as experience
with Objective C, so all the OO concepts or the mechanics of C I know very
well. But what I'm having trouble figuring out is the details of what the
C++ language does for you, and what it doesn't do for you, with all the
complexities of memory management.

I'm talking a class on C++ at my local community college, which is working
well at it's intended purpose of motivating me to actually put the time in
to learn the langauge, but it's not working well at actually teaching me
anything because I'm way ahead of the class (I think I might know C and C++
better than the teacher). Though it's a second semester class listed as
"Advanced C++", it's really just "Beginning Programming in C++ - class II"
as he's still going basic concepts like pointers and what a class is.

Unfortunately, I have started my programming straight from C++ and do
not know C at all so i can't help too much here. Also I am too newbie to
explain the things you want to know.

I found however one book where author tries to learn C++ and compare C
and C++. It would be worth looking at, epsecially as your experienced
come from C. It was rather neglected by me as I wanted to know only C++
not C so I did not focus on that part so i can't say more.

Here's the address:
http://mindview.net/Books/TICPP/ThinkingInCPP2e.html

It's Thinking in C++ by Bruce Eckel and he also provide exercises at the
end of every chapter. I can't say how complex are problems for a
regular programmer but I have learned a lot from this book.
 
T

Tony

James Kanze said:
Curt Welch wrote:
If he's looking to understand under the hood, I don't think that
the Koenig and Moo will be what he's looking for.

That doesn't read like you intended it to for most people I think.
Just the
opposite, maybe---they orientation is to get you programming
rapidly and effectively without understanding the underlying
details.

Tony
 
J

James Kanze

That doesn't read like you intended it to for most people I think.

I can only see one way of reading it (but maybe there are too
many negations in the formulation). The Koenig and Moo teaches
programming, not how the compiler works. It explicitly deals
with higher level abstractions: you learn to use std::vector,
and iterators, rather than pointers and raw memory. While IMHO,
this is what is important, and certainly what you should start
with, the orginal poster explicitly said he was looking for
something else.
 
T

Tony

That doesn't read like you intended it to for most people I think.

"I can only see one way of reading it (but maybe there are too
many negations in the formulation). The Koenig and Moo teaches
programming, not how the compiler works. It explicitly deals
with higher level abstractions: you learn to use std::vector,
and iterators, rather than pointers and raw memory. While IMHO,
this is what is important, and certainly what you should start
with, the orginal poster explicitly said he was looking for
something else."

At first glance, it seemed (to me) that the OP was looking for things like
"concrete C++ data type" and "bitwise copy" and the like, which I don't
consider low level. After actually _reading_ the OP's post, I think one
thing he's asking for is a tome of some sort that describes all the compiler
activities that occur with class objects whether concrete or not. Anyways,
given that, I found more than one way to grok your comment. I think there
are chapters in "Accelerated C++" that may give _some_ insight to _some_
issues to the OP, but I think the info he is looking for isn't compiled in a
single place (but I haven't been looking for such info either to know
whether it is or not).

Tony
 
C

Curt Welch

James Kanze said:
I can only see one way of reading it (but maybe there are too
many negations in the formulation). The Koenig and Moo teaches
programming, not how the compiler works. It explicitly deals
with higher level abstractions: you learn to use std::vector,
and iterators, rather than pointers and raw memory. While IMHO,
this is what is important, and certainly what you should start
with, the orginal poster explicitly said he was looking for
something else.

Yeah, being the original poster, I'll have to say that your message seemed
clear to me the first time and I only see one way to read it. I ordered a
copy of TC++PL.

I need to just get started with C++ features quickly as well, but my long
history of C forces me to think about memory management as a C programmer
so I can't just ignore all the stuff I've spent a life time developed a
very healthy paranoia for and just "trust" it works right without seeing
for a fact that it does work right while at the same time developing a good
enough understanding of where it stops working right (when you use new).
I'm getting there. :)

It's fun seeing just how different you have think about the langauge.
Someone else in this thread said something to the effect that they "just
trust it works" and I'm seeing how that's true and I'm getting there.

I go way back with C - back to the days that you couldn't even pass, or
return a long value on the stack, let along pass or return structures or
assign them. And even though C has come a long way in that time (even
before C++), I still think in the mentality that in practical applications,
you don't pass "big things" like structs by value and you don't return them
by value. In practical code, if you really need an an Object like think in
C code, you implement it as a structure which is _always_ dynamically
allocated with malloc(). You write new and free routines for it, and all
your code references them with pointers. And you take extreme care in your
code structure to be sure never to allocate one extra, and you take extreme
care to clean up after yourself so when the program terminates there are
_zero_ objects left allocated. If you ever "cheat" and create one of your
struct objects as a local variables for example, (instead of making it a
pointer and calling your new routine to create it) you are highly likely to
get yourself into trouble by either not having it initialized correctly, or
by having some other routine mistakenly try to free it, or someone holding
a pointer to it after it's gone.

But because C++ has made pass by value work (and all the complex calls to
constructors and destructors and automatic use of all the temps as needed),
the standard way of dealing with struct objects (aka class objects) is to
do just the opposite of what I've come to learn is "right" in straight C.
That is, by default you don't use pointers to objects and allocate
everything on the heap. As the other poster said, you just use them, and
think of them, like you would other built in types like int. You let the
compiler allocate space for them instead of having them only in the heap,
you pass them by value if they aren't too large (by reference if they are),
and you return them by value just as if they were something like an int --
alt least for the smaller simpler objects.

So in C, your code is full of -> operators as the stand way of dealing with
object-like things and you almost never see . in C++ it's just the other
way, and you mostly see the use of . and you have a lot less use for ->.

Learning to think differently like this is what is hard to get from most
typical C++ books because they are written assuming you have no bias that
needs to be "fixed" and they just show you without question how it's done
in C++. But as a long time C program who has written a lot of OS level
stuff and lot of long running servers (Usenet servers for example) you
can't just "ignore" that stuff and not expect your code to crash down the
the road after a few months of running. If you want to write C code that
runs as single long running process for _years_ without crashing, you have
to be hyper sensitive to these things.

It sure is a joy to be able to create and use simple objects in a C
environment and just know the compiler is going to take care of all that
for you as long as your write your object correctly. I'm having fun
already! :)

I've enjoyed working in the other OO languages where you really do ignore
(almost) all the memory management problems and it's fun to see it here
mixed in the middle of C code. I really should have learned C++ a long
time ago instead of waiting this long.

It's funny becuase I was at what I think was probably one of the first
conference that Bjarne Stroustrup gave a talk outside Bell Labs on his new
C++ preprocessed for C (a San Francisco USENIX conference in the early '80s
if my memory is correct). A left the talk thinking, why would you want to
clutter up C with all that crap?. I didn't see anything he was suggesting
hat actually added anything useful to the langauge. The big thing I failed
to grasp, and the thing you can't easily emulate in straight C without
things becoming a complete mess, is polymorphism and class inheritance (aka
the power of virutal functions). Most the other stuff you could implement
well enough simply by disciplined coding practice and the use of functions.
Though C++ had lots of features to make the other syntactically cleaner
than would result in straight C, where C falls apart completely is when you
try to hand-code polymorphism by building function lookup tables or passing
around pointers to functions.

It wasn't until many years later (early 90's) when I learned Smalltalk and
got to do a large project in it that I finally saw and understood the full
glory of the OO approach (what Stroustrup had seen with Simula in the late
70's). I've done work with many OO languages over the years - but by fate,
never C++ until now.

I think I should have paid a little more attention at that talk and figured
out why he was so excited about it instead of ignoring it. :)
 
C

Curt Welch

Tony said:
"I can only see one way of reading it (but maybe there are too
many negations in the formulation). The Koenig and Moo teaches
programming, not how the compiler works. It explicitly deals
with higher level abstractions: you learn to use std::vector,
and iterators, rather than pointers and raw memory. While IMHO,
this is what is important, and certainly what you should start
with, the orginal poster explicitly said he was looking for
something else."

At first glance, it seemed (to me) that the OP was looking for things
like "concrete C++ data type" and "bitwise copy" and the like, which I
don't consider low level. After actually _reading_ the OP's post, I think
one thing he's asking for is a tome of some sort that describes all the
compiler activities that occur with class objects whether concrete or
not. Anyways, given that, I found more than one way to grok your comment.
I think there are chapters in "Accelerated C++" that may give _some_
insight to _some_ issues to the OP, but I think the info he is looking
for isn't compiled in a single place (but I haven't been looking for such
info either to know whether it is or not).

Tony

Yeah, I don't need exact compiler bit for bit implementation details, I
just need to know all the abstractions required to write C++ code
correctly. However, since C and C++ are languages extremely close to the
hardware, the abstractions required end up being nearly compiler specific
details becuase most the compiler specific details end up being exposed to
the programmer (as though the sizeof operator, and unlimited pointer
manipulation).

For someone just starting in C++, most the specifics can be, and typically
are, left out. But to really know the language, you need to understand all
the specifics. I was getting frustrated by the books I was reading not
giving me enough details for my taste.

For example, when you simply declare:

SomeObject x;

It was not clear to me if x was the memory for the object, of if, like with
Java, the variable was really a pointer to the object with the object
allocated automatically on the heap. That's the type of detail the C++
books don't start out talking about, but which I, as a long time C
programmer, want to know first off. You can read a few chapters of a
typical C++ book and still have no clue whether "SomeObject x" was
allocating a pointer on the stack or allocating the object itself on the
stack. I eventually figured out it was allocating the object on the stack,
but that you can declare pointers and allocate memory yourself using new
etc.

But the same sort of confusion was happening for me with the automatic
calls to constructors and destructors. The answer is that it does most of
what it needs to do automagically so C++ books don't start out talking
about it. But as a long time C programmer, I know how careful you have to
be about these things, and how in straight C, you (the programmer) have to
be fully aware of all alloc()s and free()s and pointer ownership in data
structures and functions. And I also know that even though C++ does a lot
for you, it doesn't do everything for you like Java or Smalltalk does, so
in the long run, you can't just "trust the compiler". You have to know
exactly when the compiler does the work for you, and when it doesn't, so
when you write code that cross the "danger" line, you know you have crossed
that line and have to take great care to do the work yourself - and catch
all errors etc.

What the books weren't telling me, is where that line was - becuase the
books start off ignoring those "danger lines" and working within the area
where the compiler was talking care of everything for you.

Another example of me wondering about that "danger line" was with
destructors. If you don't include a destructor, the C++ compiler will do
the work for you. That is, if your object has in it, other objects that
have destructors (like string objects), the C++ complier will make sure all
the destructors for the mebers are called whenever your object is
destroyed. But what happens if I write my own destructor? Do I need to
manually code calls to all the destructors for all the objects in my class
since or will the C++ compler still add that code for me? The answer
(after some testing) was that the C++ compler still adds the code for you
so you don't have to do it. But when you write a destructor, you will, at
times, need to know that, and know what order destructors get called for
all base classes and your own class relative to the code you write, in
order to hunt down and find obscure bugs that can creep into complex
programs. And that's the type of thing that the books I was reading didn't
even mention, when they talked about destructors (at least not in the first
mention of destructors).

So I don't need to know the implementation details about how the C++
compiler manages to make sure all the destructors in the class hierarchy
get called, but I do need to know when they are called and what order they
are called, and when, if ever, we might (or can) code calls manually, etc.
You are not really (in my view) a C++ programmer unless you fully
understand all these sorts of obscure details about how the langauge works
and that's the stuff the books I was reading seemed to just be ignoring.

It's just going to take some time for me to pick all this up. Mostly, it's
just climbing a learning curve that requires writing a lot of code no
matter what books you are using. The TC++PL book I'm sure will help
however and that's the type of advice I was looking for when I posted.
There's just so much reference material available on C++ these days it's
hard to know where to turn without some advice.
 
T

Tony

Curt Welch said:
Yeah, I don't need exact compiler bit for bit implementation details, I
just need to know all the abstractions required to write C++ code
correctly. However, since C and C++ are languages extremely close to the
hardware, the abstractions required end up being nearly compiler specific
details becuase most the compiler specific details end up being exposed to
the programmer (as though the sizeof operator, and unlimited pointer
manipulation).

For someone just starting in C++, most the specifics can be, and typically
are, left out. But to really know the language, you need to understand
all
the specifics. I was getting frustrated by the books I was reading not
giving me enough details for my taste.

For example, when you simply declare:

SomeObject x;

It was not clear to me if x was the memory for the object, of if, like
with
Java, the variable was really a pointer to the object with the object
allocated automatically on the heap. That's the type of detail the C++
books don't start out talking about, but which I, as a long time C
programmer, want to know first off. You can read a few chapters of a
typical C++ book and still have no clue whether "SomeObject x" was
allocating a pointer on the stack or allocating the object itself on the
stack. I eventually figured out it was allocating the object on the
stack,
but that you can declare pointers and allocate memory yourself using new
etc.

The key to being able to understand the above immediately (when coming from
the world of C) is to realize that C++ was NOT developed as a
new/from-the-ground-up language like Java (pretty much) was. The behavior of
the above should be "kinda" obvious: that it is a stack object "like any
other built-in type" that C offers. The problem you had, I think, was that
you had TOO MUCH knowledge of the other languages and you "over-thought".
Had you had ONLY knowledge of C, it would have been easier to make the
correct assumptions.
But the same sort of confusion was happening for me with the automatic
calls to constructors and destructors. The answer is that it does most of
what it needs to do automagically so C++ books don't start out talking
about it.

I think the answer is there in the books, but it gets glossed-over. The
casually throw out concepts like "concrete data type", "first-class objects"
and don't dwell on or give insight to the behind-the-scenes compiler
activities. You're right, there should be a few sections in a chapter about
that stuff. For me, that kind of information was first presented to me in
Coplien's "Advanced C++" where he establishes that "concrete data type"
means the "orthodox canonical form" that consists of a default constructor,
a copy constructor, a destructor and an assignment operator. Over the years,
I've just gotten what knowledge that builds on that from a myriad of places
(and I do take most of it for granted unless something weird starts
happening and I find myself in the debugger).

Guess what the following does:

class MyObject
{
int val;
public:
MyObject(){}
~MyObject(){}
MyObject& MyObject(const MyObject& obj){ val = obj.val; }
MyObject& operator=(const MyObject& obj) { if(&obj != this) val =
obj.val; return *this; }

MyObject(int v){ val = v; };
};

MyObject obj() = 39;

You might think that the default constructor and then the assignment
operator is called. Tracing that with a debugger shows that the overloaded
constructor with the int argument is called .

That by the way is perhaps the best recommendation: experiment with the
compiler/debugger and watch what happens!

[snipped relevant, but long, similar example issues]
It's just going to take some time for me to pick all this up. Mostly,
it's
just climbing a learning curve that requires writing a lot of code no
matter what books you are using. The TC++PL book I'm sure will help
however and that's the type of advice I was looking for when I posted.
There's just so much reference material available on C++ these days it's
hard to know where to turn without some advice.

A debugger will probably be your best friend for awhile: it's quicker to
just watch what happens than reading about it, but surely the literature or
other info sources will answer any questions about why it works as it does.
Answers to thornier issues can be gotten from the many gurus who post in
this NG. Oh yea, don't forget about the c.l.c++ FAQ and googling past posts,
for issues you may be encountering, in the C++ newsgroups, as they are
another majorly good source of info and chances are someone has asked the
question a number of times before.

Good Luck!

Tony
 
C

Curt Welch

Tony said:
The key to being able to understand the above immediately (when coming
from the world of C) is to realize that C++ was NOT developed as a
new/from-the-ground-up language like Java (pretty much) was. The behavior
of the above should be "kinda" obvious: that it is a stack object "like
any other built-in type" that C offers. The problem you had, I think, was
that you had TOO MUCH knowledge of the other languages and you
"over-thought". Had you had ONLY knowledge of C, it would have been
easier to make the correct assumptions.

Yes, that's exactly the case.
I think the answer is there in the books, but it gets glossed-over. The
casually throw out concepts like "concrete data type", "first-class
objects" and don't dwell on or give insight to the behind-the-scenes
compiler activities. You're right, there should be a few sections in a
chapter about that stuff. For me, that kind of information was first
presented to me in Coplien's "Advanced C++" where he establishes that
"concrete data type" means the "orthodox canonical form" that consists of
a default constructor, a copy constructor, a destructor and an assignment
operator. Over the years, I've just gotten what knowledge that builds on
that from a myriad of places (and I do take most of it for granted unless
something weird starts happening and I find myself in the debugger).

Guess what the following does:

class MyObject
{
int val;
public:
MyObject(){}
~MyObject(){}
MyObject& MyObject(const MyObject& obj){ val = obj.val; }
MyObject& operator=(const MyObject& obj) { if(&obj != this) val =
obj.val; return *this; }

MyObject(int v){ val = v; };
};

MyObject obj() = 39;

I didn't even know you could have () for initialization without anything
inside it. So I would have guessed compiler error. Being told you can
specify the default constructor that way, my second guess would be compiler
error for trying to assign an int to the object without the correct =
operator defined. :)

Ah, but then I read your follow up to this message and see you meant to add
the int assignment operator!

But then I still didn't believe it would work so I tested it and it doesn't
on my version of gcc on FreeBSD at least (gcc version 2.95.4 20020320
[FreeBSD]).

MyObject obj() = 39;

Is a function named obj returning a MyObject and you can not initialize
that with 39. At least that's how I read it.

But changing it to what I guess you meant:

MyObject obj = 39;
or
MyObject obj(39);

And that complies.
You might think that the default constructor and then the assignment
operator is called. Tracing that with a debugger shows that the
overloaded constructor with the int argument is called .

Well, with my two rewrites, you would expect the int constructor to be
called since both are valid constructor syntax, so I'm not sure what you
are suggesting.

Certainly C++ constructor syntax is confusing because with a single
argument constructor you can use the = operator syntax which makes one
think that these two would be the same:

MyObject obj = 1;

vs.

MyObject obj;
obj = 1;

When they are not, since the first is really the same as:

MyObject obj(1);

But that's something I did already understand and wasn't confused by.
That by the way is perhaps the best recommendation: experiment with the
compiler/debugger and watch what happens!

Yeah, I do that endlessly when I have issues like this I want to understand
(and to be sure my understanding is correct when I have any doubt).
[snipped relevant, but long, similar example issues]
It's just going to take some time for me to pick all this up. Mostly,
it's
just climbing a learning curve that requires writing a lot of code no
matter what books you are using. The TC++PL book I'm sure will help
however and that's the type of advice I was looking for when I posted.
There's just so much reference material available on C++ these days
it's hard to know where to turn without some advice.

A debugger will probably be your best friend for awhile: it's quicker to
just watch what happens than reading about it, but surely the literature
or other info sources will answer any questions about why it works as it
does. Answers to thornier issues can be gotten from the many gurus who
post in this NG. Oh yea, don't forget about the c.l.c++ FAQ

Yeah, I was just reading over that last night. Lots of good stuff in
there. Lots to keep me busy and thinking for some time as well...
and googling

It's surprising just how well Googling for answers to C++ questions works.
There seem to be so many specific web pages dedicated to C++ Q&A I can
often find specific answers extremely quickly that way.
past posts, for issues you may be encountering, in the C++ newsgroups, as
they are another majorly good source of info and chances are someone has
asked the question a number of times before.

Good Luck!

Tony

Yeah, and checking questions other people ask in the group is a both a good
way to test your knowledge, and expand it. When I know the answer to 99%
of all the questions asked, I'll feel I know the langauge. :) I've got a
long way to go still to get to that point...
 
T

Tony

Curt Welch said:
Tony said:
The key to being able to understand the above immediately (when coming
from the world of C) is to realize that C++ was NOT developed as a
new/from-the-ground-up language like Java (pretty much) was. The behavior
of the above should be "kinda" obvious: that it is a stack object "like
any other built-in type" that C offers. The problem you had, I think, was
that you had TOO MUCH knowledge of the other languages and you
"over-thought". Had you had ONLY knowledge of C, it would have been
easier to make the correct assumptions.

Yes, that's exactly the case.
I think the answer is there in the books, but it gets glossed-over. The
casually throw out concepts like "concrete data type", "first-class
objects" and don't dwell on or give insight to the behind-the-scenes
compiler activities. You're right, there should be a few sections in a
chapter about that stuff. For me, that kind of information was first
presented to me in Coplien's "Advanced C++" where he establishes that
"concrete data type" means the "orthodox canonical form" that consists of
a default constructor, a copy constructor, a destructor and an assignment
operator. Over the years, I've just gotten what knowledge that builds on
that from a myriad of places (and I do take most of it for granted unless
something weird starts happening and I find myself in the debugger).

Guess what the following does:

class MyObject
{
int val;
public:
MyObject(){}
~MyObject(){}
MyObject& MyObject(const MyObject& obj){ val = obj.val; }
MyObject& operator=(const MyObject& obj) { if(&obj != this) val =
obj.val; return *this; }

MyObject(int v){ val = v; };
};

MyObject obj() = 39;

I didn't even know you could have () for initialization without anything
inside it. So I would have guessed compiler error. Being told you can
specify the default constructor that way, my second guess would be
compiler
error for trying to assign an int to the object without the correct =
operator defined. :)

Ah, but then I read your follow up to this message and see you meant to
add
the int assignment operator!

But then I still didn't believe it would work so I tested it and it
doesn't
on my version of gcc on FreeBSD at least (gcc version 2.95.4 20020320
[FreeBSD]).

MyObject obj() = 39;

Is a function named obj returning a MyObject and you can not initialize
that with 39. At least that's how I read it.

But changing it to what I guess you meant:

MyObject obj = 39;

OK, that's what I meant then.
or
MyObject obj(39);

That would be an invalid to my example.
And that complies.

I didn't check it, but it probably does that on my platform also then. I
wrote the example without testing it. The example is still valid though even
with that correction though.
Well, with my two rewrites, you would expect the int constructor to be
called since both are valid constructor syntax, so I'm not sure what you
are suggesting.

I was suggesting that someone may think that the default constructor would
be called first and then the overloaded assignment operator.
Certainly C++ constructor syntax is confusing because with a single
argument constructor you can use the = operator syntax which makes one
think that these two would be the same:

MyObject obj = 1;

vs.

MyObject obj;
obj = 1;

When they are not, since the first is really the same as:

MyObject obj(1);

But that's something I did already understand and wasn't confused by.

Well, that was my example though. "When all else fails, trust the
compiler/debugger"!
That by the way is perhaps the best recommendation: experiment with the
compiler/debugger and watch what happens!

Yeah, I do that endlessly when I have issues like this I want to
understand
(and to be sure my understanding is correct when I have any doubt).
[snipped relevant, but long, similar example issues]
It's just going to take some time for me to pick all this up. Mostly,
it's
just climbing a learning curve that requires writing a lot of code no
matter what books you are using. The TC++PL book I'm sure will help
however and that's the type of advice I was looking for when I posted.
There's just so much reference material available on C++ these days
it's hard to know where to turn without some advice.

A debugger will probably be your best friend for awhile: it's quicker to
just watch what happens than reading about it, but surely the literature
or other info sources will answer any questions about why it works as it
does. Answers to thornier issues can be gotten from the many gurus who
post in this NG. Oh yea, don't forget about the c.l.c++ FAQ

Yeah, I was just reading over that last night. Lots of good stuff in
there. Lots to keep me busy and thinking for some time as well...
and googling

It's surprising just how well Googling for answers to C++ questions works.
There seem to be so many specific web pages dedicated to C++ Q&A I can
often find specific answers extremely quickly that way.
past posts, for issues you may be encountering, in the C++ newsgroups, as
they are another majorly good source of info and chances are someone has
asked the question a number of times before.

Good Luck!

Tony

Yeah, and checking questions other people ask in the group is a both a
good
way to test your knowledge, and expand it. When I know the answer to 99%
of all the questions asked, I'll feel I know the langauge. :) I've got a
long way to go still to get to that point...

One doesn't have to be a language guru to be a good developer though. I
would say that it's not even the most important part, unless one is coding
to someone else's design and specializing on the programming aspect of
software development. Programming languages come and go, but applications
persist beyond the tools.

Tony
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,053
Latest member
BrodieSola

Latest Threads

Top