• Welcome to Overclockers Forums! Join us to reply in threads, receive reduced ads, and to customize your site experience!

C++: Is it safe to immediatly use the address after a constructor?

Overclockers is supported by our readers. When you click a link to make a purchase, we may earn a commission. Learn More.

mccoyn

Senior Member
Joined
Nov 17, 2003
Location
Michigan, USA
Is this code safe?

Code:
class myClass
{}

void foo(myClass* ptr)
{
    // Do something with ptr.
}

int main()
{
    foo(&myClass()); // Is this line safe?
}

VS.NET 2005 doesn't give me a warning and the program works, but will it always work?
 

marker

Member
Joined
Mar 20, 2005
mccoyn said:
Is this code safe?

Code:
class myClass
{}

void foo(myClass* ptr)
{
    // Do something with ptr.
}

int main()
{
    foo(&myClass()); // Is this line safe?
}

VS.NET 2005 doesn't give me a warning and the program works, but will it always work?


A the point which you are using the pointer, the object you are passing (a temporary instance of myClass on the stack) is full constructed should never be a problem.

You should even be able to use a pointer to an object from within the objects own constructor provided that you do use any member fields/variables that have not yet been created and/or initialized. Memory for the object is acually allocated by the compiler before the constructor is called.
 

MRD

Senior Member
Joined
Feb 14, 2003
I'm confused here. What exactly are you passing to foo? You need to first create an object of type myClass. You can't pass it the name of the class, you must pass it an instantiation of the class.
 
OP
mccoyn

mccoyn

Senior Member
Joined
Nov 17, 2003
Location
Michigan, USA
I called the constructor, which creates a temporary object on the stack. Then I passed the address of that temporary object to the function.

The thing I'm worried about is when is the compilier free to destroy the temporary object? It works on MSVS 2005, but is that because this particular compilier is being conservative on when to destroy it?

If your wondering, my actual problem is more complicated. myClass is a polymorphic type and the constructor being called is for a derived type. It would defeat the purpose to write a version of foo for every possible derived type.
 

MRD

Senior Member
Joined
Feb 14, 2003
Just write foo for the parent class, then cast the pointer of the derived class as a pointer for the parent class.
 
OP
mccoyn

mccoyn

Senior Member
Joined
Nov 17, 2003
Location
Michigan, USA
Thats what I'm doing except that the cast is implicit. I expect that the code I wrote should do the same as this:

Code:
class myClass
{}

void foo(myClass* ptr)
{
    // Do something with ptr.
}

int main()
{
    myClass explicitTemp();
    foo(&explicitTemp);
}

I just don't want to write all that out (I do it many times.)
 

MRD

Senior Member
Joined
Feb 14, 2003
I am not 100% sure. I'm not convinced that the object is persistent the way you are doing it. I would use the 2nd way. Declare the object first, then pass it to foo.
 

marker

Member
Joined
Mar 20, 2005
mccoyn said:
The thing I'm worried about is when is the compilier free to destroy the temporary object?

If the compiler is properly implemented, the object will not be freed until after all of your code in the function. In your case the memory is on the stack, but the rules are the same. Calling conventions (stdcall, cdecl, pascal, etc.) dictate who (caller or callee) is responsible for freeing the space on the stack (among other things like the order of parameters). In either case, the memory will freed (pop'd) from the stack until at the very least the cleanup code (compiler generated) of the callee (foo). Think of it as just a special case of passing an integer (or any other built-in type) by value (not reference - pointer). For example foo(int i){}. You can access and modify i (which exists on the stack) until the end of the function.

There is no difference (at least in foo) between explicitly defining a variable to hold the instance or letting the compiler create a temp var to hold the instance. The only limitation is that you will not be able to use the instance ofter the call to foo(). In that case (which you do not seem to need) you would need to explicitly define a variable to hold the instance.

I know, kind of long winded, but I tried to cover "all the bases".