在构造函数中初始化的变量未保持初始化(c ++)

时间:2014-04-07 15:30:14

标签: c++ variables visual-c++ c++11 constructor

我已经在C ++工作了一段时间,但我以前从未遇到过这个错误。我有一个结构(名为skew_value),它有一个初始化方法,所以一切都可以有正确的默认值(如果它有一个以上的构造函数和析构函数,我使它成为一个类而不是一个结构)。我已经验证了构造函数确实被调用(断点)。并且正确设置变量。但是一旦构造函数完成,一切都是未初始化的。

代码如下:

#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是一个包含两个float变量的类。缩放通常是其中之一,但我将其切换为两个浮点变量来测试问题不在于Vector2f类。

您可以给出关于为何调用构造函数的任何解释,但是所有被解除初始化的变量都会很棒。无论我是否将类作为指针,都会发生这种情况。我调用哪个构造函数或者提供参数也没关系。它只是在调用构造函数后拒绝跟踪数据。

2 个答案:

答案 0 :(得分:7)

问题是您没有使用这些值返回正在初始化的对象。您对skew_value构造函数的调用采用float参数构造并初始化一个临时的匿名自动skew_value对象,但不会将其复制到您应该构建的对象中,也不会对其进行修改。因此,这些变化并未反映在最终返回的对象中。

C ++不是Java或C#,您可以通过这种方式本地调用嵌套构造函数(来自函数体)。

<强>然而...

C ++ 11引入了这种能力;你只是没有使用正确的语法。它应该像初始化列表参数一样调用。

你应该说:

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功能无法使用
然后你必须做很长时间,并建议使用初始化列表来初始化你的所有值。

其他参考
在此相关问题中查找更多可能与以下内容重复的问题:Can I call a constructor from another constructor (do constructor chaining) in C++?

答案 1 :(得分:0)

在此代码中,

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));
}

中间的构造函数调用正在创建临时并初始化它。

C ++ 11确实支持构造函数转发,但它有不同的语法,我从来没有使用它,你的编译器可能不一定支持它。

相反,我建议您使用基类构造函数或对象工厂函数。我不会使用init方法,因为有充分的理由不这样做(Bjarne在他的第3版“C ++编程语言”的例外安全附录中讨论了一些)。但最终可能就是你最终会做的事情,并且在你开始要求客户端代码来调用它之前并没有那么危险。


请注意,您要离开成员变量TLIndexTRIndexBLIndexBRIndex 未初始化。这意味着他们将拥有不确定的值。对于一些编译器和选项,这些值将为0,但对于其他编译器和选项,它们将显然是任意的,并且很容易成为错误的来源。


还要注意预处理器符号

_LBMOON_GRAPHICSYSTEM_SKEW_VALUE_H

无效。所有使用下划线后跟大写字母的名称都保留给实现。包含两个后续下划线的名称也是如此。

在这种情况下,我怀疑你会得到任何无意的文本替换或重新定义效果,但真正有悖常理的编译器可能会将此视为错误,无论如何,这是一个最好纠正的坏习惯。 ; - )