a) When you call a function in C++ the compiler has to generate code to process the parameters and then jump to the code containing the function. The called function has to set up a bunch of data structures to handle things like exceptions and returning from the function. These all take space in the executable file and time to execute. If a function is small this overhead can dwarf any code actually in the function. A decent optimising compiler will do an analysis of the code and execution size of a function and if it looks like the code will be smaller and/or faster it'll dump a copy of the code for the function at the calling site.
is a hangover back to the days when optimisers were a bit crap. All it does is say to the compiler "I think this is a short function that could do with inlining." In them days of yore most compilers would reply "yay, someone cares!" and
the code for you and not bother checking whether it was a good idea or not. These days most compilers will usually reply "I was going to do that anyway" or "what are you? Mad? That's way too big!" and then ignore the keyword. The upshot is on modern compilers
doesn't do a lot for your code - a bit like the
So if I were you I wouldn't bother using it anymore. Unless you're writing template classes but that's more down to the fact that most compilers don't support the
keyword and another story entirely.
b) In C++
is virtually the same as
. The only difference is that all members of a
by default. One of the previous posters is talking complete rubbish - they can have ordinary member functions, virtual functions, constructors and destructors, just likes
. Where you use
is really a matter of style - some bodies of code use
for everything apart from aggregates of data (which they use
for), others use
for things like functors and interface classes. Experiment with different styles and see which one hits the spot for you and if you code for a living make sure you at least consider the local coding styles to avoid scaring the natives.
is just like
with one important difference*. Every data member overlays all the others. This is great when dealing with hardware but not so great when some idiot overlays a
. The only time you ever need a
is when you have a set of bits that you need to interpret in more than one manner and don't want to litter your code with casts and bitwise operations. Sometimes the code can be clearer with casts though so if you ever have to do this sort of thing make sure you try various ways and see which one looks the least confusing and surprising for the audience.
So there are three ways of declaring and defining things that behave like classes but there are differences. Admittedly the difference between
are fairly minimal.
c) If you have a
with a single argument constructor, e.g:
foo( int n );
and a function that takes an argument of type foo or
void bar( foo f )
then weird things can happen. Anywhere the rest of your code wants a foo you can supply an
and the code will work, or at least compile:
bar( 87 );
Wherever the code expects a foo and you supply an
the compiler will create a temporary of class foo and initialise it with the int. Then after the statement it appears in it will destroy the temporary (unless the temporary is bound to a const reference in the scope it's created in, ho, ho, ho...).
This can be very handy if the conversion makes sense at all times (e.g. the conversion between a string literal and a std::string can make code far easier to read) but it can introduce subtle errors ("Hang on, how come I'm passing a number into that function and I'm getting code called I didn't know existed!").
For those occasions when the automatic conversion everywhere doesn't make a lot of sense you can mark single argument constructors as
. It says "If you want to use this constructor you have to do so explicitly by mentioning the name of the class." You have to code all your calls to
as something like:
bar( foo( 87 ) );
Anyway, hope this lot helps. Ignore
, don't sweat it about
- you probably won't need it, and use
to turn off automatic conversions that don't make a lot of sense.
*That's not strictly true - unions can't have virtual functions or static member data. They can have member functions though including constructors and destructors though.