Hi,
When is the constructor called in a situation like this?
Tricky one..Code:class MyClass
{
public:
MyClass() { cout << "Hi" << endl; }
static MyClass * GetInstance() { static MyClass myClass; return &myClass; }
};
Printable View
Hi,
When is the constructor called in a situation like this?
Tricky one..Code:class MyClass
{
public:
MyClass() { cout << "Hi" << endl; }
static MyClass * GetInstance() { static MyClass myClass; return &myClass; }
};
Have you tried stepping through the code in a debugger?
Won't that pretty much answer the question for you?
No. Nevermind, I do not feel like explaining why this situation could be tricky.
To be honest, the code doesn't make a lot of sense. It's kind of like a singleton, but not really since you need an instance to access the GetInstance method.
AFAIK static globals are constructed before main() is called. I'm not sure about static locals of member functions, though.
But in your particular case I doubt that this would compile at all: Classes are not allowed to contain members of their own type (only pointers are allowed), and I somehow suppose that this applies to static member function locals as well.
OTOH, the rule that class members of the class' own type are not allowed is based on the fact that this would result in infinite object size. I think this would not apply to static member function locals, but I'm not sure whether the creators of the standard introduced an extra exception to the general rule for people doing daring things like you do... :D
A method does not contribute to the size of a class..
It compiles, I tested and the constructor is called the first time I use GetInstance(), so not before main(), which is the weird thing, because the compiler can't know when the first call to the constructor must be made in a complex code.
I forgot in my sample code to put 'static MyClass *' , i did that now.
I don't find it weird at all. the static object is confined by the scope of the static function even though the lifespan is not restricted. it would make sense for it to be constructed on first entry.Quote:
Originally Posted by ProgrammerC++
Quote:
3.3.1 Point of declaration [basic.scope.pdecl]
1 The point of declaration for a name is immediately after its complete declarator (clause 8) and before its
initializer (if any)
Only global object may get initialized before main and not local static scoped objects.Quote:
6.7.4 The zero-initialization (8.5) of all local objects with static storage duration (3.7.1) is performed before any
other initialization takes place. A local object of POD type (3.9) with static storage duration initialized with
constant-expressions is initialized before its block is first entered. An implementation is permitted to perform
early initialization of other local objects with static storage duration under the same conditions that an
implementation is permitted to statically initialize an object with static storage duration in namespace scope
(3.6.2). Otherwise such an object is initialized the first time control passes through its declaration; such an
object is considered initialized upon the completion of its initialization. If the initialization exits by throwing
an exception, the initialization is not complete, so it will be tried again the next time control enters the
declaration. If control re-enters the declaration (recursively) while the object is being initialized, the behavior
is undefined.
Quote:
3.6.3 It is implementation-defined whether or not the dynamic initialization (8.5, 9.4, 12.1, 12.6.1) of an object of
namespace scope is done before the first statement of main. If the initialization is deferred to some point
in time after the first statement of main, it shall occur before the first use of any function or object defined
in the same translation unit as the object to be initialized.
Hopefully this answers a few questions...Quote:
3.3.3 The outermost declarative region of a translation unit is also a namespace, called the global namespace. A
name declared in the global namespace has global namespace scope (also called global scope). The potential
scope of such a name begins at its point of declaration (3.3.1) and ends at the end of the
to put this in 'plain code' what the compiler essentially does for you in this...
more or less gets turned into:Code:static MyClass * MyClass::GetInstance()
{
static MyClass myClass;
return &myClass;
}
So this does what's required, the static MyClass object gets constructed at the first time the function gets called, which is how it's supposed to be.Code:static byte MyClassData[sizeof(MyClass)];
static bool bObjectConstructed = false;
static MyClass * MyClass::GetInstance()
{
if (!bObjectConstructed)
{
bObjectConstructed=true;
((MyClass*)MyClassData)->MyClass();
}
return ((MyClass*)MyClassData);
}
class DestroyObjects
{
~DestroyObjects()
{
if (bObjectConstructed)
{
((MyClass*)MyClassData)->~MyClass();
}
}
};
DestroyObjects objDestroyAtExit;
The usual complaint about the method-local static is that its construction isn't thread-safe.
So the question arises: what about a static variable in an inner scope? Will it be constructed when it first comes into scope, in which case it could be protected, or when the function is first called, in which case it can't?
Code:static MyClass & MyClass::GetInstance()
{
mutex mlock(creationmutex);
{
static MyClass myClass;
return myClass;
}
}