Skip to main content
gamedev.net
🔒 Locked

constructors / initialization madness [solved]

Started by Falken42 May 28, 2006 at 9:14 AM 3 replies 550+ views
Original Post
Falken42
Falken42
Hello all, I'm having a problem with the order of static constructors not being called in the order I desire on startup and wrecking all sorts of havoc. Since my code is quite a bit complicated, I'll try to simplify. Given a simple "Texture" class, for example -- it wants to register itself to some kind of a manager in its constructor:
static std::vector<MyTexture *> textureManager;

MyTexture::MyTexture()
{
    textureManager.push_back(this);

    // ...do stuff here...
}



Until now, all of my MyTexture objects have been created inside or after main() was called, so there haven't been any problems. I recently tried creating a static MyTexture outside of main() and have found that the textureManager vector hasn't been initialized yet (_Buy(0) hasn't been called so the internal _Myfirst, _Mylast, _Myend variables are just garbage). Just to make sure, I put a breakpoint inside the vector() constructor and my classes' constructor, and my class got initialized first. Surely there must be quite a few people out there who have done something like this before. I did a fairly exhaustive forum search, but nothing seemed to turn up. The only way I can see how to fix this is to declare textureManager as a pointer, and dynamically create it if it hasn't been allocated before. Something like this, perhaps:
static std::vector<MyTexture *> *textureManager = NULL;

MyTexture::MyTexture()
{
    if (textureManager == NULL)
        textureManager = new std::vector<MyTexture *>;

    textureManager->push_back(this);

    // ...do stuff here...
}


But this just seems really yucky. Plus, I can't use the C++ operators directly, so I'd have to do:

MyTexture *tex = (*textureManager)[idx];
Is there anyone who's dealt with this before? What's the best way to handle a situation like this? Any thoughts / opinions are welcome. [Edited by - bpoint on May 28, 2006 9:47:07 AM]
Enigma
Enigma
My personal preference (if I really only need one texture manager) is to replace:
static std::vector< MyTexture * > textureManager;

with
namespace{	std::vector< MyTexture * > & textureManager()	{		static std::vector< MyTexture * > textureManagerInstance;		return textureManagerInstance;	}}

Just be careful that no destructors of static objects depend on textureManager unless their constructors also call it.

Σnigma
rip-off
rip-off
Relying on the order of static constrution is bad in c++, AFAIK it is undefined. The best thing to do would be to make it so that there are as few statics as possible. In my code, I used to have 2 global statics, these have been reduced to gglobal pointers pointing to an object allocated inside main, as will (someday) be removed as globals.

If you dont want to do this, you _may_ want to look into the singleton design pattern, this is one of the reasons such a construct exists. It will guarentee that the object is constructed before its first use, and if it isnt used, it will not be constructed.

Be aware that singletons can be a sign of bad design, as they are so easy to be put in, but due to the global availability of them they can lead to hard to find errors.

But in your case, since the textureManager variable is local to the file it is defined in, this shouldn't be too bad.

Finally, using the static keyword to limit a symbols scope as lost favour, anonymus namespaces are preffered:

namespace{   std::vector<MyTexture *> textureManager;} // end anonymus namespace


The usage of the symbol doesn't change.

[edit: or what they said. :/ I'm getting slower ]
Falken42
Falken42
Hmm... I'll admit, I hadn't considered using a static function that just returns a static instance of the vector. This seems easy enough to implement and is still nice and clean.

Thanks for the quick replies, everyone!

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.