Inlining Constructors

M

Michael Hull

Hi,
I remember from somewhere reading that inlining constructors is a
'BadThing', but now can't seem to find the original source. I can't
however thing of a reason why it would be for simple constructors...
any thoughts


Mike
 
V

Vineet Chawla

Hi,
I remember from somewhere reading that inlining constructors is a
'BadThing', but now can't seem to find the original source. I can't
however thing of a reason why it would be for simple constructors...
any thoughts

Mike

Hi,
For simple constructors of classes having implicit data types as their
data members only it is ok to have inline constructors but even it is
not getting derived.

But for heavy classes (classes with many user defined data types as
data members) inlining constructors is a bad thing and it becomes even
more worse if the class is inherited from some other class.

When you will look at the number of lines in the constructor you will
feel it should be allowed, but an object construction results in
calling so many constructor calls (of all composed objects and of all
base classes and their composed objects).

Please correct me if i am wrong.

Vineet
 
S

Sylvester Hesp

Vineet Chawla wrote :
Hi,
For simple constructors of classes having implicit data types as their
data members only it is ok to have inline constructors but even it is
not getting derived.

But for heavy classes (classes with many user defined data types as
data members) inlining constructors is a bad thing and it becomes even
more worse if the class is inherited from some other class.

When you will look at the number of lines in the constructor you will
feel it should be allowed, but an object construction results in
calling so many constructor calls (of all composed objects and of all
base classes and their composed objects).

You're describing WHEN it is bad, but not WHY it is bad, so this is not
helping. I can think of several reasons: inlining large functions
causes massive code bloat, thus increasing the size of your executable
and probably decreasing performance. Another reason might be that the
larger the constructor is, the more dependencies (on average) it has on
the rest of the code, causing you to rebuild large parts of your
application for even small changes that don't have to do anything with
the users of the constructor in question.

However, these reasons all apply to regular functions as well, and the
threadstarter was explicitely talking about constructors. Besides that,
keep in mind that 'inline' is only a hint to the compiler - a good
compiler will make his own judgements on whether to inline a function
or not, no matter if the constructor/function was actually defined as
being inline, so the first argument is pretty moot.

So to conclude, I have no idea why inlining constructors in particular
is a Bad Thing.

- Sylvester
 
J

Juha Nieminen

Sylvester said:
Besides that,
keep in mind that 'inline' is only a hint to the compiler

It's not *only* a hint. It does more than that (specifically
related to linking).
 
S

Sylvester Hesp

Juha said:
It's not *only* a hint. It does more than that (specifically
related to linking).

Yes I might've been a bit unclear. I wasn't talking about the inline
keyword in general, I was talking about the actual process of function
inlining by the compiler.

- Sylvester
 
V

Vineet Chawla

Yes I might've been a bit unclear. I wasn't talking about the inline
keyword in general, I was talking about the actual process of function
inlining by the compiler.

- Sylvester

If you see the third paragraph in my reply there i have mentioned why
it is bad.

Yes i agree with your point that it is just a hint to the compiler. I
don't know if there is some other reason as well for this.

Regards
Vineet
 
J

John Harrison

Vineet said:
If you see the third paragraph in my reply there i have mentioned why
it is bad.


Yes i agree with your point that it is just a hint to the compiler. I
don't know if there is some other reason as well for this.

Regards
Vineet

The fact that you write a method, function or constructor inline does
*NOT* force the compiler to inline the code and cause 'massive code
bloat'. I would be very disappointed in such a stupid compiler.

People get so confused about inlining. As Juha said the meaning of
inline is to tell the compiler not to apply the 'one definition rule',
i.e. it means it's OK to put the function definition in a header file.
Whether it's a good idea to do this or not is primarily a style issue.

Whether a function's code is inlined is an optmization issue, and I
would exect a good compiler not to inline some functions I had declared
inline, and also to inline some functions I had not declared inline.
Both of these things are optmizations which the compiler can work out
for itself. VC++ 2005 does this.

john
 
M

Michael Hull

The fact that you write a method, function or constructor inline does
*NOT* force the compiler to inline the code and cause 'massive code
bloat'. I would be very disappointed in such a stupid compiler.

People get so confused aboutinlining. As Juha said the meaning of
inline is to tell the compiler not to apply the 'one definition rule',
i.e. it means it's OK to put the function definition in a header file.
Whether it's a good idea to do this or not is primarily a style issue.

Whether a function's code is inlined is an optmization issue, and I
would exect a good compiler not to inline some functions I had declared
inline, and also to inline some functions I had not declared inline.
Both of these things are optmizations which the compiler can work out
for itself. VC++ 2005 does this.

john

Thanks for all the replies..... most of this is covered in the FAQ, i
was wondering whether the Constructor is a special case in particular,
i.e, If I have a simple, POD class, is there a reason not to inline
the constructor (except the standard reasons of not inlining...) ?

Thanks for the replies


Mike
 
J

James Kanze

[...]
Thanks for all the replies..... most of this is covered in the FAQ, i
was wondering whether the Constructor is a special case in particular,
i.e, If I have a simple, POD class, is there a reason not to inline
the constructor (except the standard reasons of not inlining...) ?

The main reason for the special rule concerning constructors
(and destructors) is that even if the function looks trivial, it
might not be, which is not normally the case for other
functions. At least one place I worked (a long time ago) did
have a rule in the coding guidelines against inlining
constructors and destructors.

Several things have changed since then. Projects have become
larger (so dependency management becomes more important),
function calls faster, and the most frequent general rule today
is not to inline anything until the profiler says to do so. On
the other hand, templates in the absense of export means that
the dependencies are there anyway, so some guidelines are more
liberal with regards to inlining template functions (where they
allow templates).
 
S

Sylvester Hesp

James said:
[...]
Thanks for all the replies..... most of this is covered in the FAQ, i
was wondering whether the Constructor is a special case in particular,
i.e, If I have a simple, POD class, is there a reason not to inline
the constructor (except the standard reasons of not inlining...) ?

The main reason for the special rule concerning constructors
(and destructors) is that even if the function looks trivial, it
might not be, which is not normally the case for other
functions. At least one place I worked (a long time ago) did
have a rule in the coding guidelines against inlining
constructors and destructors.

Just out of interest, what did those guidelines say about simple
aggregates containing lots of members that have no trivial
constructors?

struct Foo
{
Type1 a;
Type2 b;
Type3 c;
// etc.
};

It has no defined default constructor, so one is generated. But the
generated constructor can be very expensive, and you have no control
over whether it gets inlined. Did those guidelines said you should
define a non-inlined constructor to circumvent compiler inlining?

- Sylvester
 
J

John Harrison

It has no defined default constructor, so one is generated. But the
generated constructor can be very expensive, and you have no control
over whether it gets inlined.

You have no control in standard C++ over whether any
constructor/method/function gets inlined.

I feel I'm repeating myself here.

john
 
C

Clark Cox

Just out of interest, what did those guidelines say about simple
aggregates containing lots of members that have no trivial constructors?

struct Foo
{
Type1 a;
Type2 b;
Type3 c;
// etc.
};

It has no defined default constructor, so one is generated. But the
generated constructor can be very expensive, and you have no control
over whether it gets inlined.

Nor will you.
Did those guidelines said you should define a non-inlined constructor
to circumvent compiler inlining?

There is no way to prevent the inlining of *any* function (constructor or not).
 
J

James Kanze

James said:
[...]
Thanks for all the replies..... most of this is covered in the FAQ, i
was wondering whether the Constructor is a special case in particular,
i.e, If I have a simple, POD class, is there a reason not to inline
the constructor (except the standard reasons of not inlining...) ?
The main reason for the special rule concerning constructors
(and destructors) is that even if the function looks trivial, it
might not be, which is not normally the case for other
functions. At least one place I worked (a long time ago) did
have a rule in the coding guidelines against inlining
constructors and destructors.
Just out of interest, what did those guidelines say about simple
aggregates containing lots of members that have no trivial
constructors?
struct Foo
{
Type1 a;
Type2 b;
Type3 c;
// etc.
};
It has no defined default constructor, so one is generated. But the
generated constructor can be very expensive, and you have no control
over whether it gets inlined. Did those guidelines said you should
define a non-inlined constructor to circumvent compiler inlining?

Yes. It goes back some, but there was a rule against using the
compiler generated defaults; every class was supposed to have an
explicit copy constuctor, destructor and assignment operator
(although the copy constuctor and assignment operator could be
private).

It's probably overdoing it, but memory was a lot scarcer back
then, so we worried about code bloat.
 
S

Sylvester Hesp

John said:
You have no control in standard C++ over whether any
constructor/method/function gets inlined.

I feel I'm repeating myself here.

Uhm, if you had followed the thread completely, you'll find that I
myself was the first to mention that you don't have any control over
it.

However, you have more control over what functions *not* to inline than
you have control over what functions *do* inline. Most compilers will
not inline functions of which the definition is not known at use-time.
E.g., when the function is defined in a separate translation unit.

- Sylvester
 
J

John Harrison

Sylvester said:
Uhm, if you had followed the thread completely, you'll find that I
myself was the first to mention that you don't have any control over it.

True, apologies.
However, you have more control over what functions *not* to inline than
you have control over what functions *do* inline. Most compilers will
not inline functions of which the definition is not known at use-time.
E.g., when the function is defined in a separate translation unit.

- Sylvester

It's not that simple. VC++ 2005 does inline functions even when in
seperate translation units. They call it 'whole program optmisation',
its done by the linker of course.

john
 
G

Gennaro Prota

James said:
[...]
Thanks for all the replies..... most of this is covered in the FAQ, i
was wondering whether the Constructor is a special case in particular,
i.e, If I have a simple, POD class, is there a reason not to inline
the constructor (except the standard reasons of not inlining...) ?
The main reason for the special rule concerning constructors
(and destructors) is that even if the function looks trivial, it
might not be, which is not normally the case for other
functions. At least one place I worked (a long time ago) did
have a rule in the coding guidelines against inlining
constructors and destructors.
Just out of interest, what did those guidelines say about simple
aggregates containing lots of members that have no trivial
constructors?
struct Foo
{
Type1 a;
Type2 b;
Type3 c;
// etc.
};
It has no defined default constructor, so one is generated. But the
generated constructor can be very expensive, and you have no control
over whether it gets inlined. Did those guidelines said you should
define a non-inlined constructor to circumvent compiler inlining?

Yes.

I'm a bit surprised. I thought the answer would be that in general you
didn't *ask* for inlining (with the inline keyword, or by defining the
member function in-class). The idea being that one wouldn't waste time
writing code/making a request unless there was a reason (profiling)
for doing so.

And of course there's in general the fact that, request or not, the
compiler may pretty much inline whatever it wants.
It goes back some, but there was a rule against using the
compiler generated defaults; every class was supposed to have an
explicit copy constuctor, destructor and assignment operator
(although the copy constuctor and assignment operator could be
private).

It's probably overdoing it, but memory was a lot scarcer back
then, so we worried about code bloat.

Yep. It looks like premature optimization to me. But, as you say, it's
an old guideline.

I think the current trend is to be as explicit as possible in pretty
much anything. Projects have become increasingly larger, and it seems
established that anything intentional is better spelled out in code as
"hey, maintenance programmer, it's me!... this was intentional!" :)
Francis' proposal n1717 - Explicit class and default definitions,
about which I asked on comp.std.c++, explicit conversion operators,
explicit namespaces (fixing ADL) and others all go in this direction,
IMHO. Now, some of these won't make it into C++0x but, I guess, for
time constraints and other reasons, not because they weren't
considered useful.
 
J

James Kanze

I'm a bit surprised. I thought the answer would be that in general you
didn't *ask* for inlining (with the inline keyword, or by defining the
member function in-class). The idea being that one wouldn't waste time
writing code/making a request unless there was a reason (profiling)
for doing so.

No. This was some fifteen years ago, the program was very close
to the limits of available memory, and code bloat was a serious
issue.

Today, of course, the situation is a bit different, and I doubt
that the rules would be quite so rigorous.
And of course there's in general the fact that, request or not, the
compiler may pretty much inline whatever it wants.

In theory, at least. In practice, 15 years ago, if the code for
a function wasn't present in the translation unit, that function
wouldn't be inlined.

Today, of course, and to a large degree, even back then, the
main reason for avoiding inlining---even to the point of
providing versions which do exactly what the compiler does, is
to reduce compiler dependencies. No one really cares whether a
function is inlined or not, but you don't want to have to
recompile all of the client code just because some minor
implementation detail has changed. And this still leads to
defining functions which the compiler would otherwise declare,
so that you can add additional behavior later without
recompiling the world. This obviously doesn't apply, however,
to "classes" that are just agglomerations of data, and given
compile times on modern machines, it likely doesn't apply to
small, or even medium size projects. (Although on most projects
I work on, "compile times" are conditionned by network speeds,
and not CPU speeds. And while there's been some improuvement
there, it is far from the same order of magnitude as that of
CPUs.)
Yep. It looks like premature optimization to me. But, as you say, it's
an old guideline.

And one that developped because we were having serious problems
with code bloat. (I don't know if it helped any, of course. I
rather suspect that the problems with code bloat were
elsewhere:).)
 
M

Marcus Kwok

Michael Hull said:
Thanks for all the replies..... most of this is covered in the FAQ, i
was wondering whether the Constructor is a special case in particular,
i.e, If I have a simple, POD class, is there a reason not to inline
the constructor (except the standard reasons of not inlining...) ?

Just a note: as soon as you define your own constructor, it is no longer
a POD.
 
G

Gennaro Prota

No. This was some fifteen years ago, the program was very close
to the limits of available memory, and code bloat was a serious
issue.

Ah, okay. I thought we were talking of guidelines established *before*
the start of the project.
Today, of course, the situation is a bit different, and I doubt
that the rules would be quite so rigorous.


In theory, at least. In practice, 15 years ago, if the code for
a function wasn't present in the translation unit, that function
wouldn't be inlined.

Yes. FWIW, I was thinking of it both ways though: it can inline "at
will" and refuse to inline at will.
Today, of course, and to a large degree, even back then, the
main reason for avoiding inlining---even to the point of
providing versions which do exactly what the compiler does, is
to reduce compiler dependencies. No one really cares whether a
function is inlined or not, but you don't want to have to
recompile all of the client code just because some minor
implementation detail has changed. And this still leads to
defining functions which the compiler would otherwise declare,
so that you can add additional behavior later without
recompiling the world.

Sure. Which brought another idea to my mind: the standard proposals
about new syntaxes for explicitly requesting the generation of class
members all attack the declaration of the function. This means that if
you later have to switch to a user-defined implementation you have
still to change the header: they are just addressing the issue of
being explicit about the intent. I guess it would be more useful to
address the coupling issue and attack the definition instead, with
something like:

// .hpp
class X
{
...
X & operator=( const X & ); // "normal" declaration
};

// .cpp
X &
X::eek:perator=( const X & ) = auto;

No?
 
C

Charles Bailey

Marcus said:
Just a note: as soon as you define your own constructor, it is no longer
a POD.

Is that true?

BS ISO/IEC 14882:2003 (Second Edition)
3.9 (10) says that POD-structs are POD types, and 9 (4) says that a
POD-struct is an aggregate class which has no non-static data members of
type non-POD-struct, non-POD-union (or array of such types) or
reference, and has no user-defined copy assignment operator and no
user-defined destructor. There's no mention of constructors.

Is there a ban on constructors in a paragraph that I've missed?
 

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

Forum statistics

Threads
474,294
Messages
2,571,511
Members
48,199
Latest member
MarielIzzo

Latest Threads

Top