Initialize const global variable.

I've been trying to use const global variables but they never seem to be initialized even after main() has begun executing.

I'm trying to create bit masks using std::bitset because i want bit masks larger than 32 bits, which an enum doesn't seem to allow. So my globals look something like this.

"Bitmasks.h"
1
2
3
4
5
6
7
8
  #include <bitset>

  typedef std::bitset<64> BitMask;

  extern const BitMask MASK_ONE;
  extern const BitMask MASK_TWO;
  extern const BitMask MASK_THREE;
  ...etc


"Bitmasks.cpp"
1
2
3
4
5
6
  #include "Bitmask.h"

  const BitMask MASK_ONE   = BitMask(1);
  const BitMask MASK_TWO   = BitMask(1 << 1);
  const BitMask MASK_THREE = BitMask(1 << 2);
  ...etc


But these always seem to be set to zero whenever i try to actually use them.

"main.cpp"
1
2
3
4
5
6
7
8
9
  #include "Bitmask.h"

  int main()
  {
    BitMask test = MASK_THREE; //This should set the third bit to 1 but it dosn't, all bits are 0.
    test = BitMask(1 << 2);    //This works, the third bit is now set to 1.

    return 0;
  }


I don't understand why they are not initialized even after main() has begun.
I've read you can force initialization if you change the global variable into a static variable within a global function, the function initializes the variable on first use then just returns a reference to the variable.

But that would mean writing a function for every variable, also i'm likely to be using these bit masks hundreds, if not thousands of times a second, wouldn't the function calls effect performance? Isn't there another way?

Sorry for the verbose explanation but i wanted to explain exactly what i'm doing even if the problem has nothing to do with bitsets.
Last edited on
Objects at namespace scope will be initialised before the first statement in main.
Do you have multiple versions of "Bitmasks.cpp" floating around?

http://coliru.stacked-crooked.com/a/0d759b1f550f70f0
http://coliru.stacked-crooked.com/a/c7823a828288e5e3
http://coliru.stacked-crooked.com/a/f41d2953924a5213
I just created a new project and tried the code samples and it works perfectly, but in my current project the initialize strings are never called so it's like the cpp file is completely ignored, i guess that means there's something wrong in my current project? There's only one cpp file that defines the masks.

Also i didn't know you could do this

const BitMask MASK_ONE = ( ( std::cout << "initialise MASK_ONE\n" ), BitMask(1) ) ;

What do you call inlining a statement like that? I'd like to learn the syntax.
Last edited on
Copy initialise a BitMask object:
const BitMask MASK_ONE = <some expressioin that evaluates to a BitMask object>

Sequencing (comma) operator (non-overloaded):
expression1 , expression2
Evaluation and side effects of expression1 is sequenced before evaluation and side effects of expression2.
expression1 is evaluated and its value is discarded.
The type and value of the result of expression1 , expression2 is the type and value of expression2

( ( std::cout << "initialise MASK_ONE\n" ), BitMask(1) )
first evaluates ( std::cout << "initialise MASK_ONE\n" ) and discards the result.
then evaluates BitMask(1) which is the result of the expression
The bitmask is initialised with const BitMask MASK_ONE = BitMask(1) ;

The precedence of the sequencing operator is low; hence the parentheses around the expressions..


EDIT:
Any expression, the evaluation of which will print out the message and yield the appropriate result would do.
You may find this easier on the eye:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
#include <bitset>

template < typename T >
const T& evaluate_with_commentary( const char* narrative, const T& v )
{
    std::cout << narrative << '\n' ;
    return v ;
}

template < typename T >
T& evaluate_with_commentary( const char* narrative, T& v )
{
    std::cout << narrative << '\n' ;
    return v ;
}

const std::bitset<64> MASK_ONE = evaluate_with_commentary( "initialise MASK_ONE", 1 ) ;

const std::bitset<64> MASK_TWO = evaluate_with_commentary( "initialise MASK_TWO", std::bitset<64>( 1U << 2U ) ) ;

int count = evaluate_with_commentary( "initialise count", 345 ) ;

int& reference_to_count = evaluate_with_commentary( "initialise reference_to_count", count ) ;

int main()
{
}

http://coliru.stacked-crooked.com/a/c26d84fb1c8a8479
Last edited on
Thanks a bunch JLBorges, I actually just found out whats causing the problem. In the Visual Studio settings on my current project i have set the entry point to main(), but in the default test project i set up there is no set entry point, when i remove that setting the globals get initialized.

The reason i set the entry point to main() in the first place was because there was a conflict with a library i'm using, but now i've removed the setting there doesn't seem to be any conflict, weird.

So thanks again, and thanks for teaching me the sequencing operator.
Topic archived. No new replies allowed.