Sign in to follow this  
Sylvarant

D3DXVECTOR3

Recommended Posts

Every time i try to compile my code to draw a triangle using DirectX it says it encounters an error because it has to take a temporary adress?
// set position of camera and of what it's looking at
 if(FAILED(D3DXMatrixLookAtLH(&m_matView, 
                                 &D3DXVECTOR3(0.0f, 00.0f, -50.0f), //Position 50 units back.
                                 &D3DXVECTOR3(0.0f, 0.0f, 0.0f),    //Look at the origin
                                 &D3DXVECTOR3(0.0f, 1.0f, .0f)))){   //Up is the positive Y-Axis 

Share this post


Link to post
Share on other sites
My compiler is quite happy with that code, but I can see how it could cause trouble. You construct three D3DXVECTOR3 objects and immediately reference them without providing an alias. You may be able to appease the compiler with:

// create three temporary vectors
D3DXVECTOR3 eye = D3DXVECTOR3(0.0f, 00.0f, -50.0f);
D3DXVECTOR3 target = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
D3DXVECTOR3 up = D3DXVECTOR3(0.0f, 1.0f, .0f);

// set position of camera
if(FAILED(D3DXMatrixLookAtLH(&m_matView,
&eye, //Position 50 units back.
&target, //Look at the origin
&up))){ //Up is the positive Y-Axis



This way, you aren't passing temporary variables, but fully-fledged local ones. Your program has a grip on the variables it passes by reference.

Regards
Admiral

Share this post


Link to post
Share on other sites
and by the way, D3DXMatrixLookAtLH does not return as HRESULT so checking it's return value with the FAILED/SUCCEEDED macros is pointless. D3DXMatrixLookAtLH returns a pointer to the built matrix.

And also, which compiler are you using?

Share this post


Link to post
Share on other sites
It is correct for the compiler to complain; chances are, if your compiler does not, or does not issue a warning then either:

a) the compiler is non-standard (i.e., it's a bug)
b) the compiler is using an extension (Visual Studio does this; you can disable it)
c) The type you are taking the address of is well-defined and provides an overload for the address-of operator (see below).

But first, code like your original example (e.g., foo(&T()), where foo is a function taking a T* and T is some type) is both dangerous and illegal in most cases. It is dangerous because you are taking the address of a temporary, and foo could store that address (for example, in a global variable or a member variable, if foo() were instead a member function of same class).

However, the temporary ceases to exist after the expression completes, since there is no exception (such as binding to a reference) in this example that can prolong the lifetime of said temporary. So attempts to use the stored address later will result in a crash.

It is illegal in most cases because the operand of address-of must be an l-value; a temporary is not. It would be safe if T defined an overloaded address-of operator, because that would be a call to a member function. The caveat to item (3) that I mentioned above is that if T defines such an overload, but the expression &T() is in a context where T has only been forward-declared, not defined, then the result is undefined behavior.

Share this post


Link to post
Share on other sites
jpetrie, your post makes a lot of sense on the whole, but there's one thing that bothers me. How is this any different from a 'temporary local' variable?

// Temporary
SomeFunction(&POINT(0, 0));

// Temporary Local
{
POINT P = POINT(0, 0);
SomeFunction(&P);
}


As far as I can see, these two are equivalent. A POINT is created (at the same place) on the stack, initialised, passed by reference, and immediately destroyed after calling SomeFunction. It's just as unsafe for SomeFunction to store the address of its argument in the first case as it is in the second.
I trust that you are right, but I'd like to know what's wrong in my understanding.

Regards
Admiral

Share this post


Link to post
Share on other sites
TheAdmiral, yes, the example you gave is just as dangerous.

The address-of operator must take an l-value; it would be very dangerous to allow it to take the address of non-l-values as it would, effectively turn them into l-values.

A temporary must not be an l-value, otherwise you could do stupid and meaningless things like: T() = 42;

Those two things are dictated by the standard. To my recollection (and I'm not going to look), the standard never states explictly that "you cannot apply the address-of operator to a temporary," but the things it does state basically imply it, so that's just the way it is.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this