Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

(I know) In c++ I can declare variable out of scope and I can't run any code/statement, except for initializing global/static variables.


IDEA

Is it a good idea to use below tricky code in order to (for example) do some std::map manipulation ?

Here I use void *fakeVar and initialize it through Fake::initializer() and do whatever I want in it !

std::map<std::string, int> myMap;

class Fake
{
public:
    static void* initializer()
    {
        myMap["test"]=222;
        // Do whatever with your global Variables

        return NULL;
    }
};

// myMap["Error"] = 111;                  => Error
// Fake::initializer();                   => Error
void *fakeVar = Fake::initializer();    //=> OK

void main()
{
    std::cout<<"Map size: " << myMap.size() << std::endl; // Show myMap has initialized correctly :)
}
share|improve this question
1  
Why have you create class for that function? –  Dawid 3 hours ago

7 Answers 7

up vote 4 down vote accepted

One way of solving it is to have a class with a constructor that does things, then declare a dummy variable of that class. Like

struct Initializer
{
    Initializer()
    {
        // Do pre-main initialization here
    }
};

Initializer initializer;

You can of course have multiple such classes doing miscellaneous initialization. The order in each translation unit is specified to be top-down, but the order between translation units is not specified.

share|improve this answer
    
More generally, we may add some parameters to this constructor. –  Emadpres 2 hours ago
    
@Emadpres That's okay, you can pass arguments as usual. –  Joachim Pileborg 2 hours ago
1  
@Emadpres: That's generally not useful. As you can see from Joachim's example, the parameters passed would be passed just 5 lines upwards. Why not put them directly where you need them, inside Initializer::Initializer ? It's not like Initializer initializer; can access argc/argv or other useful variables (in the context of this question) –  MSalters 46 mins ago
    
@MSalters In my case, I need to insert the map from different source file, and each should add their specific data. So I need to have parameter in this case. –  Emadpres 36 mins ago
    
@Emadpres: Well, that runs into the problem that the map can't be a global because it may not exist when the initializers in other files run. –  MSalters 15 mins ago

§ 8.5.2 states

Except for objects declared with the constexpr specifier, for which see 7.1.5, an initializer in the definition of a variable can consist of arbitrary expressions involving literals and previously declared variables and functions, regardless of the variable’s storage duration

therefore what you're doing is perfectly allowed by the C++ standard. That said, if you need to perform "initialization operations" it might be better to just use a class constructor (e.g. a wrapper).

share|improve this answer
    
+1 fro quoting the spec –  AlexanderBrevig 3 hours ago
    
+1 for quoting. Good point to remember. –  Emadpres 2 hours ago

Is it a good idea...?

Not really. What if someone decides that in their "tricky initialisation" they want to use your map, but on some system or other, or for not obvious reason after a particular relink, your map ends up being initialised after their attempted use? If you instead have them call a static function that returns a reference to the map, then it can initialise it on first call. Make the map a static local variable inside that function and you stop any accidental use without this protection.

share|improve this answer
    
Thank you. It's mentioned here . –  Emadpres 3 hours ago

You don't need a fake class... you can initialize using a lambda

auto myMap = []{
    std::map<int, string> m;
    m["test"] = 222;
    return m;
}();

Or, if it's just plain data, initialize the map:

std::map<std::string, int> myMap { { "test", 222 } };
share|improve this answer
    
Thank you for lambda, but in my case, myMap should get initialized by different classes. –  Emadpres 2 hours ago

Is it a good idea to use below tricky code in order to (for example) do some std::map manipulation ?

No.

Any solution entailing mutable non-local variables is a terrible idea.

share|improve this answer

In C++, you cannot have statements outside any function. However, you have global objects declared, and constructor (initializer) call for these global objects are automatic before main starts. In your example, fakeVar is a global pointer that gets initialized through a function of class static scope, this is absolutely fine.
Even a global object would do provide that global object constructor does the desired initializaton. For example,

class Fake
{
public:
    Fake()     {
        myMap["test"]=222;
        // Do whatever with your global Variables
    }
};
Fake fake; 
share|improve this answer

What you've done is perfectly legal C++. So, if it works for you and is maintainable and understandable by anybody else who works with the code, it's fine. Joachim Pileborg's sample is clearer to me though.

One problem with initializing global variables like this can occur if they use each other during initialization. In that case it can be tricky to ensure that variables are initialized in the correct order. For that reason, I prefer to create InitializeX, InitializeY, etc functions, and explicitly call them in the correct order from the Main function.

Wrong ordering can also cause problems during program exit where globals still try to use each other when some of them may have been destroyed. Again, some explicit destruction calls in the correct order before Main returns can make it clearer.

So, go for it if it works for you, but be aware of the pitfalls. The same advice applies to pretty much every feature in C++!

You said in your question that you yourself think the code is 'tricky'. There is no need to overcomplicate things for the sake of it. So, if you have an alternative that appears less 'tricky' to you... that might be better.

share|improve this answer
    
I think you mean static initialization order fiasco. thanks –  Emadpres 2 hours ago

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.