Alternate way to initialise static object.

Y

Yu

I have found that the static object is initialised at the time when
the shared libary is loaded. The initialisation caused the invocation
of the constructor.
May I know of any way that I can initialize the static object without
invoking the constructor?

Below is the sample coding.

Header file ASURegistrationManager.h
#include "ASURegistration.h"

class ASURegistrationManager
{
public:
static ASURegistration& GetASURegistration();

private:
static ASURegistration ASUReg; //The static object
ASURegistrationManager();
~ASURegistrationManager();
};

Header file ASURegistration.h
#include "ApplicationInterface.h"

class ASURegistration : public IApplicationInterface
{
public:
ASURegistration();
~ASURegistration();
};

Header file ApplicationInterface.h
class IApplicationInterface
{
public:
IApplicationInterface(); //This will spawn thread
~IApplicationInterface();

};

ASURegistration.cpp
#include "ASURegistration.h"

ASURegistration::ASURegistration() : IApplicationInterface()
{
}

ASURegistration::~ASURegistration()
{
}

ASURegistrationManager.cpp
#include "ASURegistrationManager.h"

ASURegistration ASURegistrationManager::ASUReg; //This initialization
invoke the IApplicationInterface constructor to create thread.

ASURegistrationManager::ASURegistrationManager()
{
}

ASURegistrationManager::~ASURegistrationManager()
{
}

ASURegistration& ASURegistrationManager::GetASURegistration()
{
return (ASURegistration &)ASUReg;
}

ApplicationInterface.cpp
#include "ApplicationInterface.h"

using namespace std;

void *APIProcessEvent(void *pvASUInterface)// Thread Function
{
while(true)
{
sleep(5);
}
return(0);
}

IApplicationInterface::IApplicationInterface()
{
pthread_t ProcessEventThread;
pthread_attr_t attr;

cout << "In IApplicationInterface\n";

if(pthread_attr_init(&attr) != 0)
{
std::cout<<"pthread_attr_init system call for thread
failed.\n";
}

if(pthread_attr_setscope(&attr,PTHREAD_SCOPE_SYSTEM) != 0)
{
std::cout<<"pthread_attr_setscope system call for thread
failed.\n";
}

if(pthread_create(&ProcessEventThread,&attr,APIProcessEvent,NULL)
!= 0)
{
std::cout<<"Failed to create Process Event Thread.\n";
}
}

IApplicationInterface::~IApplicationInterface()
{
}


I have the cpp function that calls the static method
ASURegistrationManager::GetASURegistration().

#include <stdio.h>

#include "wrap.h"
#include "AClass.hpp"
#include "CppLibAPI.h" //This is just a combination header file of the
header files shown above.

using namespace std;
extern "C" {

void * AClass_new(int x)
{
ASURegistration& ASUReg =
ASURegistrationManager::GetASURegistration();
return ((void *)new AClass(x)); //AClass is a cpp class
}

}

The above cpp programs are compiled as a shared library .so to be used
by the C program.

The C program is as follow.

#include <stdio.h>
#include "wrap.h"
int main(void)
{
printf("main() starting\n");
return 0;
}

When I run the C program, the output is as follow:
In IApplicationInterface
main() starting

As you can see the IApplicationInterface constructor is called which
will spawn a thread before the C main function. The static method in
the AClass_new() cpp function caused the initialisation of the static
variable ASUReg which in turns invoke the IApplicationInterface
constructor. I need the thread to be spawned only at the point when
the cpp function AClass_new() is called instead of during program
initialisation. Is there other anyway to initialise the static object
such that the constructor is not invoked?

I have tried to use a static pointer. That will not cause the
invocation of the constructor at initialisation, because a pointer can
be initialised to null. But I have concerned on the static method's
return.

If I change the declaration to
static ASURegistration* ASUReg

so ASUReg can be initialised as
ASURegistration* ASURegistrationManager::ASUReg=NULL;

Is the following statement correct?

ASURegistration& ASURegistrationManager::GetASURegistration()
{
return (ASURegistration &)*ASUReg; //Will this cause any problem?
}

Thank you!
 
J

John Harrison

Sorry about the previous post, hit the send button to early.

[snip]
If I change the declaration to
static ASURegistration* ASUReg

so ASUReg can be initialised as
ASURegistration* ASURegistrationManager::ASUReg=NULL;

Is the following statement correct?

ASURegistration& ASURegistrationManager::GetASURegistration()
{
return (ASURegistration &)*ASUReg; //Will this cause any problem?
}

Thank you!

The above looks OK. You should remove the cast.

ASURegistration& ASURegistrationManager::GetASURegistration()
{
return *ASUReg;
}

john
 
E

Emlyn Corrin

Hi,

Yu said:
I have found that the static object is initialised at the time when
the shared libary is loaded. The initialisation caused the invocation
of the constructor.
May I know of any way that I can initialize the static object without
invoking the constructor?

Below is the sample coding.

Header file ASURegistrationManager.h
#include "ASURegistration.h"

class ASURegistrationManager
{
public:
static ASURegistration& GetASURegistration();

private:
static ASURegistration ASUReg; //The static object
ASURegistrationManager();
~ASURegistrationManager();
};
What about the following, I think it will only invoke the constructor on the
first call to GetASURegistration()

class ASURegistrationManager
{
public:
static ASURegistration& GetASURegistration() {
static ASURegistration ASUReg;
return ASUReg;
}

private:
ASURegistrationManager();
~ASURegistrationManager();
};
 
Y

Yu

If I change the declaration to
The above looks OK. You should remove the cast.

ASURegistration& ASURegistrationManager::GetASURegistration()
{
return *ASUReg;
}

john

Hi John,
The above will crash. The following should should my problem. Thanks!

ASURegistration& ASURegistrationManager::GetASURegistration()
{
if (!ASUReg)
{
ASURegistration asuReg = ASURegistration();
ASUReg = &asuReg;
}
return *ASUReg;
}

Yu :)
 
Y

Yu

Oops! Mistake, should have static as follow.

ASURegistration& ASURegistrationManager::GetASURegistration()
{
if (!ASUReg)
{
static ASURegistration asuReg = ASURegistration();
ASUReg = &asuReg;
}
return *ASUReg;
}
 
H

Howard

Yu said:
Oops! Mistake, should have static as follow.

ASURegistration& ASURegistrationManager::GetASURegistration()
{
if (!ASUReg)
{
static ASURegistration asuReg = ASURegistration();
ASUReg = &asuReg;
}
return *ASUReg;
}

I don't think that's valid code even. You're declaring a variable, and
assigning it the return value of a constructor? Then, getting the address
of that variable and returning its contents? I think what you want is this:

ASURegistration& ASURegistrationManager::GetASURegistration()
{
if (!ASUReg)
ASUReg= new ASURegistration();

return *ASUReg;
}

(But I would personally prefer to return the pointer itself, not a reference
to it. I didn't look at your other code to analyze how this will be called,
though.)

-Howard
 
V

Victor Bazarov

Howard said:
I don't think that's valid code even.
Why?

You're declaring a variable, and
assigning it the return value of a constructor?

There is no "return value of a constructor". The syntax

T var = T();

is a valid C++ for copy-initialising 'var' with a default-initialised
temporary. Whether 'var' is static or not doesn't matter. Of course,
it could be simply written as

static ASURegitration asuReg;

which basically does the same thing. The difference might be if the
type 'ASURegistration' is a typedef for a POD.
Then, getting the address
of that variable and returning its contents?

Sure, why the hell not? A variable is an lvalue, one may take
its address if one wants to. And returning a reference is not
the same as returning the contents, although that shouldn't hurt
either.
I think what you want is this:

ASURegistration& ASURegistrationManager::GetASURegistration()
{
if (!ASUReg)
ASUReg= new ASURegistration();

return *ASUReg;
}

(But I would personally prefer to return the pointer itself, not a reference
to it. I didn't look at your other code to analyze how this will be called,
though.)

What if there is a requirement to return a reference?

Victor
 
J

John Harrison

Yu said:
Oops! Mistake, should have static as follow.

ASURegistration& ASURegistrationManager::GetASURegistration()
{
if (!ASUReg)
{
static ASURegistration asuReg = ASURegistration();
ASUReg = &asuReg;
}
return *ASUReg;
}

This is a bit simpler (as Victor said)

ASURegistration& ASURegistrationManager::GetASURegistration()
{
if (!ASUReg)
{
static ASURegistration asuReg;
ASUReg = &asuReg;
}
return *ASUReg;
}

This is even simpler (no ASUReg pointer)

ASURegistration& ASURegistrationManager::GetASURegistration()
{
static ASURegistration asuReg;
return asuReg;
}

The rules of C++ say that asuReg will not be constructed until the first
time you call GetASURegistration.

But all of these are correct, can't tell why you get a crash.

john
 
H

Howard

Victor Bazarov said:
There is no "return value of a constructor". The syntax

I know there is no return value of a constructor. That's exactly why I
thought the code was wrong! I can't see why anyone would write a statement
like that when, as you point out below, it's simply not needed. I just
assumed it was illegal (falsely, apparently, which is why I said I didn't
"think" it was legal).
T var = T();

is a valid C++ for copy-initialising 'var' with a default-initialised
temporary. Whether 'var' is static or not doesn't matter. Of course,
it could be simply written as

static ASURegitration asuReg;

which basically does the same thing. The difference might be if the
type 'ASURegistration' is a typedef for a POD.


Sure, why the hell not? A variable is an lvalue, one may take
its address if one wants to. And returning a reference is not
the same as returning the contents, although that shouldn't hurt
either.

Well, that's a local variable, is why not, and will got out of scope.
BUT....am I correct in assuming that's why he added the "static" to the
declaration? In that case, the fact that it's local is not relevant...it
won't go out of scope, so it's address will stil be legal, right? So my
objection would be misplaced in that case.

Regarding my statement "returning its contents", I was referring to the line
return *asuReg. Meaning that he was dereferencing the pointer. I guess
that you're correct there that what is being returned is a reference, so
it's not really returning the "contents" of anything. I'm not used to
returning references like that, except in some operators (return *this). It
looked very strange to me, still...creating a local variable,
copy-initializing it from a temporary, and returning its address. It's just
not the usual way of doing that, I think you'll agree?
What if there is a requirement to return a reference?

Sure, and like I said, I didn't look to see what his exact requirements
were. And I stated it was just my preference. But my method showed the
much more common way of creating an object in this manner. (BTW, Is that
what's called a singleton?)

-Howard
 
V

Victor Bazarov

Howard said:
I know there is no return value of a constructor. That's exactly why I
thought the code was wrong! I can't see why anyone would write a statement
like that when, as you point out below, it's simply not needed. I just
assumed it was illegal (falsely, apparently, which is why I said I didn't
"think" it was legal).


Well, that's a local variable, is why not, and will got out of scope.
BUT....am I correct in assuming that's why he added the "static" to the
declaration? In that case, the fact that it's local is not relevant...it
won't go out of scope, so it's address will stil be legal, right?

Local objects declared static have lifetime until the end of
the program, not until the end of the block.
Regarding my statement "returning its contents", I was referring to the line
return *asuReg. Meaning that he was dereferencing the pointer. I guess
that you're correct there that what is being returned is a reference, so
it's not really returning the "contents" of anything. I'm not used to
returning references like that, except in some operators (return *this). It
looked very strange to me, still...creating a local variable,
copy-initializing it from a temporary, and returning its address. It's just
not the usual way of doing that, I think you'll agree?

No, I don't agree. That's how most of singletons are implemented.
The static object could be a class-wide static or a local static
of some static member or some global function that returns a pointer
or a reference to it.
[...](BTW, Is that
what's called a singleton?)

Yes, it looks pretty much like a singleton implementation.
 
J

John Harrison

Yu said:
Hi John,
Crash is due to the following code.

ASURegistration* ASURegistrationManager::ASUReg = NULL;
ASURegistration& ASURegistrationManager::GetASURegistration()
{
return *ASUReg;
}

ASUReg is initialised to NULL. I need to do some kind of assignment
first before return.

There is no problem with what you and the rest suggested. Thanks a lot
to you and all the rest for your opinions.

I think what Howard suggested is fine too. But I need to take care of
the destruction of ASUReg somewhere with "delete". Am I right?

ASURegistration& ASURegistrationManager::GetASURegistration()
{
if (!ASUReg)
ASUReg= new ASURegistration();

return *ASUReg;
}

Strictly speaking you do, although I would be tempted to just leave it. If
you do a delete then obviously you have to ensure that the delete only
happens after you no longer need the ASURegistration object and in general
that can be quite hard to do.

One of the advantages of the other methods that don't use delete is that
because destructors are called in reverse order of constructors the
ASURegstration object shuld be destroyed only after all objects that used it
are destroyed.

john
 
V

vijay

A simple code as u r trying to write a single ton class is here
//Header
class A
{
Public:
static A* p_ASingleInst;
static A* Get_SingleInstance()
{
if(!p_ASingleInst)
p_ASingleInst = new A();
return p_ASingleInst;
}
Private:
A()
}
//cpp
static A::p_ASingleInst = NULL;

I think this is what you wnated, Your const will not get called when u do
initilisation of the pointer to NULL;
Thanks
Vijay
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,479
Members
44,899
Latest member
RodneyMcAu

Latest Threads

Top