newbie: C++ static initializer (constructor vs bool)

c++ moderated

newbie: C++ static initializer (constructor vs bool)

Postby andrew_nuss@yahoo.com » Thu, 31 Aug 2006 03:45:38 GMT

Hi,

This is obviously a newbie question.  I know that constructors for
static class instances are invoked in different modules in
unpredictable order.  My question is whether this is true of static
boolean variables as well.  For example, in the following code, I'm
wondering if the Digest::Hash() function can be called safely from
other initializers, which would be true if the "inited" boolean is
guaranteed to be set to its initial value before any static
constructors are invoked in any modules.  If the same unpredictability
of static initializer order applies to booleans then this code is
unsafe.  Which is the case?

// Digest.h

class Digest {
     enum { RANGE = 1000 }; // 1000 precalculated values
     static bool       inited;       // set to false in Digest.cpp
     static int*        array;        // array of hash values created
by constructor (set to null in Digest.cpp)

     static int LCG (int v);       // slow computation of munged "v"

     static void Init ()
     {
          array = reinterpret_cast<int*>(malloc(sizeof(int)*RANGE));
          ... fill array with precalc values
          inited = true;
     }

     public:

     // ??? can Hash() be called in different module during
     // static C++ initializer time when inited is garbage true-like
value
     // and therefore array is a garbage pointer value, then Crash!

    static int Hash (int v)
    {
        if (!inited) Init();
        if ((unsigned int)v < (unsigned int)RANGE)
             return array[v];
        else
             return LCG(v);
    }
};


// Digest.cpp

bool Digest::inited = false;
int* Digest::array = 0;

int Digest::LCG (int v)
{
   ....
}


      [ See  http://www.**--****.com/ ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]


Re: newbie: C++ static initializer (constructor vs bool)

Postby Jens Theisen » Thu, 31 Aug 2006 08:29:57 GMT



Your suspicion that booleans (and other built-in types) are initialised 
first is correct. In fact, any global or static POD member is just laid 
out in the executable you're loading directly, and no real 
initialisation is happening. That's the reason why you specify a value 
at definition for those types (as your comment says you did), but not 
for non-PODs.

So you're code is safe in that regard. Some unrelated comments:


1. Use new rather than malloc (malloc is C)

2. Use static_cast for this kind of cast. Use const_cast and 
dynamic_cast in other cases. Never use the legacy C-style cast you used 
below, and also never use reinterpret_cast unless you know exactly what 
you're doing.

So better is:

array = new int[RANGE];

Even better is to use a container so you don't deal with memory 
management yourself.

Then, since these are not built-in types, you have the problem of 
initialisation order again. Thus, I'd also suggest using function-scope 
statics, as these are guaranteed to be initialised in order of first use:

struct Digest
{
    Digest()
    {
       // init mArray here
    }

    int Hash(int v)
    {
       return mArray[v];
    }

    std::vector< int > mArray;
};

Digest const& getGlobalDigest()
{
    static Digest singleton;
    return singleton;
}

int main()
{
    int x = getGlobalDigest().Hash(42);
}

(untested)

Jens

      [ See  http://www.**--****.com/ ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]


Re: newbie: C++ static initializer (constructor vs bool)

Postby kanze » Thu, 31 Aug 2006 21:14:53 GMT




The type has nothing to do with it.  The difference is that
static initialization occurs before dynamic initialization.  For
initialization to be static, the initialized type must have a
trivial constructor (which is the case of all built-in types,
like boolean, and all POD structs), and the initialization must
be from a constant expression.  So:

    bool b1 = true ;            //  static
    bool b1 = f()  ;            //  dynamic


As long as the initialization is static, it will occur before
any line of code you write (including code used in dynamic
initialization) takes place.  Even before static initialization
(conceptually, at least---there's no way you can see the order)
is zero initialization.  Not a few initialization tricks are
based on this as well.





IMHO,
    new int[ RANGE ]
would seem more appropriate to allocate the memory.








Just a question, but is there any reason why you don't use the
standard singleton pattern here?


      [ See  http://www.**--****.com/ ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]


Re: newbie: C++ static initializer (constructor vs bool)

Postby andrew_nuss@yahoo.com » Thu, 31 Aug 2006 23:49:27 GMT




I'm actually not using malloc!  I'm having to use memory allocated by
java.nio.ByteBuffer in the JVM which I slurp into a SuperHeap data
structure of my own managing.  The second issue is this is used to
build a faster intset than a redblack tree, based on random digest of
key.  This intset is a bottleneck of the whole program, and I want my
Digest::Hash to be 100% inlined except when the check of the init
boolean returns false.  That's why I don't use the singleton pattern.
Its a few extra instructions, as well as a JSR.

Thanks for your tip on the zero value that happens before the non-zero
value.  I can't imagine what tricks could be done with that!


      [ See  http://www.**--****.com/ ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]


Similar Threads:

1.initializer Vs assignment list in constructor

On Jan 16, 8:09 am, Jack Klein < XXXX@XXXXX.COM > wrote:
> On Tue, 15 Jan 2008 22:51:15 -0800 (PST), Pallav singh
> < XXXX@XXXXX.COM > wrote in comp.lang.c++:

> > How can we justify that  initializer  list is better in
> > performance than assignment list in constructor of C++ ??

> Why would we want to justify it?  The C++ standard does not
> specify or require such a thing.

> An initializer list is the preferred way to initialize the
> members in a constructor.  It is the only possible way to
> initialize reference members and constant members.  So just
> use initializer lists.

You might add that by using an initializer list, you reduce the
chances of accidentally using the variable before it has been
initialized.  It's part of the larger philosophy of never
defining a variable without initializing it.

James Kanze (GABI Software)             email: XXXX@XXXXX.COM 
Conseils en informatique orient objet/
                   Beratung in objektorientierter Datenverarbeitung
9 place Sard, 78210 St.-Cyr-l'ole, France, +33 (0)1 30 23 00 34

2.initializer Vs assignment list in constructor

How can we justify that  initializer  list is better in performance
than assignment list in constructor of C++ ??

3.bool vs BOOL

4.Back to BOOL vs. bool

These BOOL/bool discussions drive me crazy.  Just when I think I have a
handle on what's going on, something else crops up.


(Visual C 6.0, by the way)

Code snippet 1:
CString szbuf;
BOOL  bFlag = szbuf.Empty();


Code snippet 2:
CString szbuf;
bool bFlag =szbuf.Empty();


So guess which one generates "C4800 warning C4800: 'int' : forcing
value to 'true' or 'false' (performance warning)"?

#2?  Yup.  But why?  'BOOL' is the 'int' definition, 'bool' is the
type.  And since Empty() is defined as returning a 'bool', why doesn't
#1 generate the warning?  And why would number# 2 as it does return
'bool?

You'd think I'd have better things to do with my time rather than
booling around with this stuff...

5.bool vs. BOOL

6. Ordering of C++ constructor initializers

7. Mimicking Javas static class initializer in C++

8. Constructor initializers



Return to c++ moderated

 

Who is online

Users browsing this forum: No registered users and 41 guest