tags:

views:

90

answers:

3

Stepping through the debugger, the BBox object is okay at the entry of the function, but as soon as it enters the function, the vfptr object points to 0xccccc. I don't get it.

  1. What is causing this ?
  2. Why is there a virtual table reference in there when the object is not derived from other class. (Though, it resides in GameObject from which my Player class inherits and I retrieve the BBox from within player. But, why does the BBox have the reference ? Shouldn't it be player who should be maintained in that reference ?)

For 1; some code for reference:

A. I retrieve the bounding box from player. This returns a bounding box as expected. I then send its address to GetGridCells.

 const BoundingBox& l_Bbox = l_pPlayer->GetBoundingBox();

 boost::unordered_set < Cell*, CellPHash >& l_GridCells = GetGridCells ( &l_Bbox ); 

B. This is where a_pBoundingBox goes crazy and gets that garbage value.

 boost::unordered_set< Cell*, CellPHash > CollisionMgr::GetGridCells(const BoundingBox *a_pBoundingBox)
 {

I think the following code is also pertinent, so I'm sticking this in here anyways:

 const BoundingBox& Player::GetBoundingBox(void)
 {
 return BoundingBox( &GetBoundingSphere() );
 }

 const BoundingSphere& Player::GetBoundingSphere(void)
 {
 BoundingSphere& l_BSphere = m_pGeomMesh->m_BoundingSphere;

 l_BSphere.m_Center = GetPosition();

 return l_BSphere;
 }

 // BoundingBox Constructor
 BoundingBox(const BoundingSphere* a_pBoundingSphere);

Can anyone please give me some idea as to why this is happening? Also, if you want me to post more code, please do let me know.

Thanks!

+3  A: 
 const BoundingBox& Player::GetBoundingBox(void)
 {
 return BoundingBox( &GetBoundingSphere() );
 }

Here, you're returning a reference to a temporary BoundingBox object. That object goes out of scope as soon as the return statement ends.

Return a BoundingBox instead of a BoundingBox& instead.


Also:

 BoundingSphere& l_BSphere = m_pGeomMesh->m_BoundingSphere;

 l_BSphere.m_Center = GetPosition();

Here, you take a reference to the bounding sphere of the m_pGeomMesh, then modify the value it refers to. This will result in a modification of the original object. Are you sure this is what you want?


Also:

 // BoundingBox Constructor
 BoundingBox(const BoundingSphere* a_pBoundingSphere);

In the only place where using a reference makes a great deal of sense, you use a pointer instead. Why?

Thomas
but it is returning a const-reference. Isn't the object guaranteed to be valid until the caller holding the reference goes out of scope? I agree it would have been problem if it was non const reference. But I vaguely remember there is special rule for const reference.
Naveen
There is indeed such a rule, but it doesn't apply here. The `const` reference to the object gets created in the `return` statement, then copied as the return value, after which the original `const` reference goes out of scope and the object gets destroyed. (Somebody else might correct me on the technical details, but I'm pretty sure that this `const` reference does not prolong the scope of anything.)
Thomas
Thomas is right. If the function was returning a temporary and that temporary was bound to the reference then the lifetime would be extended. But in this case the temporary is internal to the function. Consider that if the functions are in two different translation units, the compiler cannot possibly know whether the reference returned by the function refers to a temporary or not.
David Rodríguez - dribeas
Thanks for the clarifications..got it now.
Naveen
Thanks everyone for helping me out.@Thomas: BoundingSphere l_BSphere.m_Center = GetPosition();// Yep, I want to translate the sphere..so am aware this modifies the original object. // BoundingBox Constructor BoundingBox(const BoundingSphere* a_pBoundingSphere);I am often required to convert btw BBox and BSphere, thus if I make it a reference, I run into the problem of cyclic dependeny in header files. Even though, I use inclusion guards, I would need to include each of them in the other. Can you please suggest me a better way to solve this ?
brainydexter
Also, I understand that returning to a const does not prolong the scope of a variable, but then how does this happen:"If the function was returning a temporary and that temporary was bound to the reference then the lifetime would be extended"
brainydexter
In case if anyone else is interested and stuck with the same dilemna, I also got some more answers over here:http://www.gamedev.net/community/forums/topic.asp?topic_id=567816
brainydexter
@brainydexter: You can predeclare the classes without including their headers, e.g. `class BoundingSphere; class BoundingBox { ... };`.
Thomas
@brainydexter: What dribeas means is: "If you return a value (not a reference) from the function, then bind it to a `const` reference *in the calling function*, its lifetime would be extended to the scope of the calling function."
Thomas
@Thomas: For "If you return a value (not a reference) from the function, then bind it to a const reference in the calling function, its lifetime would be extended to the scope of the calling function."I created a new question since it was going out of scope of this question:http://stackoverflow.com/questions/2615162/return-value-not-a-reference-from-the-function-bound-to-a-const-reference-in-t
brainydexter
A: 
  1. As Thomas says, the BoundingBox is created by the return statement and destroyed at the end of the return statement, because it is a temporary. Returning a const reference isn't the same as assigning to a persistent const reference (which does prolong a temporary). Returning a value and assigning it to something in the caller's scope has no overhead due to copy elision, although you might have to define a copy constructor.
  2. The vtable is created if the class has any virtual methods, such as the destructor. If you had derived classes which overrided those methods, the base vtable would be required to find the correct override. All that can happen in another compilation unit so the compiler is unlikely to optimize it out.
Potatoswatter
The first point is right on, but I have tried reading the second point three times already and don't understand it.
David Rodríguez - dribeas
brainydexter
@brainy: BoundingSphere should not contain a vtable just because it creates a member in some class. `virtual` must have been used somewhere in its definition. Feel free to post more code in your question.
Potatoswatter
@Potatocorn : Ah, yes! You are correct. I have a habit of making the destructor virtual and I just realized it after you mentioned. I think that would explain the existence of vtable.<code>class BoundingSphere;class BoundingBox{public: BoundingBox(const BoundingSphere* a_pBoundingSphere); //BoundingBox( const BoundingBox virtual ~BoundingBox(void); const std::vector< glm::vec3 > GetCorners() const; glm::vec3 m_Center; glm::vec3 m_Extents; // extents along the X, Y, Z axis for the bounding box positioned at the center};</code>
brainydexter
Grr..how do I format the code correctly in comments, so that it shows up properly ?
brainydexter
@brainy: Use backticks, `.
Potatoswatter
A: 

@Thomas: Here are m classes:

#ifndef BOUNDINGBOX_H
#define BOUNDINGBOX_H

class BoundingSphere;

class BoundingBox
{
public:

    BoundingBox(const BoundingSphere* a_pBoundingSphere);
    //BoundingBox( const BoundingBox& rhs);
    virtual ~BoundingBox(void);

    const std::vector< glm::vec3 > GetCorners() const;

    glm::vec3 m_Center;
    glm::vec3 m_Extents;        // extents along the X, Y, Z axis for the bounding box positioned at the center
};

#endif

#ifndef BOUNDINGSPHERE_H
#define BOUNDINGSPHERE_H

class BoundingBox;

class BoundingSphere
{
public:
    BoundingSphere();

BoundingSphere(const BoundingBox* a_pBoundingBox);

    BoundingSphere(const glm::vec3& a_Center, const float& a_Radius);
    virtual ~BoundingSphere(void);

    // Access the Center
    const glm::vec3 &GetCenter(void) const  { return(m_Center);     };
    void SetCenter(const glm::vec3 &Center) { m_Center = Center;    };

    // Access the Radius
    float GetRadius(void) const     { return(m_Radius);     };
    void SetRadius(float Radius)    { m_Radius = Radius;    };

    glm::vec3 m_Center;
    float m_Radius;
};

#endif

Now, the way I understand this is: If in the constructor of BoundingBox has a reference to BoundingSphere instead of a pointer, i.e.

BoundingBox(const BoundingSphere& a_pBoundingSphere);

It would require the definition of BoundingSphere to be available at the time it compiles. Thus, I'll have to include BoundingSphere.h in BoundingBox.h to make the definition available. This holds true for vice versa, and thereby creates cyclic references.

Please correct me on this..

Thanks

brainydexter