Search code examples
c++c++11variablesconstructor

Variables initialized in constructor not staying initialized (c++)


I've been working in C++ for awhile now, but I've never encountered this error before. I have a struct (named skew_value) that has an initialization method so that everything can have proper default values (if it has more than a constructor and destructor, I make it a class instead of a struct). I've verified that the constructor is indeed being called (break points). And the variables are being properly set. But once the constructor is finished, everything is uninitialized.

The code is as follows:

#ifndef _LBMOON_GRAPHICSYSTEM_SKEW_VALUE_H
#define _LBMOON_GRAPHICSYSTEM_SKEW_VALUE_H

struct skew_value
{
    skew_value(float tlX=1, float tlY=0, float trX=0, float trY=0, float blX=0, float blY=0, float brX=0, float brY=0)
    {
        skew_value(Vector2f(tlX,tlY), Vector2f(trX,trY), Vector2f(blX,blY), Vector2f(brX,brY));
    }

    skew_value(Vector2f topLeft, Vector2f topRight, Vector2f bottomLeft, Vector2f bottomRight)
    {
        TLSkew = topLeft;
        TRSkew = topRight;
        BLSkew = bottomLeft;
        BRSkew = bottomRight;

        xScale = 1;
        yScale = 1;
    }

    float xScale;
    float yScale;

    Vector2f TLSkew;
    Vector2f TRSkew;
    Vector2f BLSkew;
    Vector2f BRSkew;

    Vector2f TLOrigin;
    Vector2f TROrigin;
    Vector2f BLOrigin;
    Vector2f BROrigin;

    unsigned int TLIndex;
    unsigned int TRIndex;
    unsigned int BLIndex;
    unsigned int BRIndex;
};



#endif

Vector2f is a class containing two float variables. Scale is normally one of these, but I switched it to two float variables to test that the problem didn't lie in the Vector2f class.

Any explanation you can give as to why the constructor is being called, but then all the variables being de-initialized would be great. It happens whether I make the class a pointer or not. It also doesn't matter which constructor I call or if I provide arguments. It just refuses to keep track of the data after the constructor has been called.


Solution

  • The problem is that you aren't returning the object you are initializing with those values. Your call to skew_value constructor taking float arguments constructs and initializes a temporary anonymous automatic skew_value object but doesn't copy it into the object you are supposed to be constructing nor does it modify it. As such the changes aren't reflected in the object ultimately returned.

    C++ isn't Java or C# where you can call nested constructors natively this way (from the body of a function).

    However...

    C++11 introduced this ability; you just aren't using the proper syntax for it. It should be called like an initializer list argument.

    You should instead say:

    struct skew_value
    {
        skew_value( float tlX=1, float tlY=0, float trX=0,
                    float trY=0, float blX=0, float blY=0,
                    float brX=0, float brY=0)
        : skew_value( Vector2f( tlX, tlY ), 
                      Vector2f( trX, trY ), 
                      Vector2f( blX, blY ), 
                      Vector2f( brX, brY ) )
        {
        }
    
        skew_value(Vector2f topLeft, Vector2f topRight, 
                   Vector2f bottomLeft, Vector2f bottomRight)
        {
            TLSkew = topLeft;
            TRSkew = topRight;
            BLSkew = bottomLeft;
            BRSkew = bottomRight;
    
            xScale = 1;
            yScale = 1;
        }
        ....
    }
    

    IF C++11 features can't be used
    Then you will have to do it the long way and again it's suggested to use an initializer list to initialize all of your values.

    Additional Reference
    Find more in this related question which might this might be a duplicate of: Can I call a constructor from another constructor (do constructor chaining) in C++?