通过例程初始化聚合

时间:2013-09-30 13:57:52

标签: c++ arrays initialization

我正在使用例程来初始化类的聚合成员。

class MyClass
{
public:
    void Init()
    {
        double  array2D[10][10] = {0.0};
        bool    logicalarray[2] = {false};
    }

private:
    double  array2D[10][10];  
    bool    logicalarray[2]; 
};

int main()
{
    MyClass* myClassObject = new  MyClass();
    myClassObject->Init();

    delete myClassObject;
    return 0;
}

这有什么问题吗?它编译,构建和运行良好。在调试时,我确实看到每个数组元素都是按照我在Init()中定义的方式进行初始化。但是,代码清理工具报告在Init()中,声明了命名变量但未引用。

PS:没有C ++ 11

1 个答案:

答案 0 :(得分:1)

代码清理工具是对的。此代码不符合您的想法:

void Init()
    {
        double  array2D[10][10] = {0.0};
        bool    logicalarray[2] = {false};
    }

认为此代码初始化MyClass的成员变量。它实际上做的是声明两个本地(自动)变量,初始化它们,然后返回。不会触及成员变量,并且Init()的{​​{1}}内部是hidden

您可以通过以下方式解决此问题:

void Init()
    {
        array2D[10][10] = {0.0};
        logicalarray[2] = {false};
    }

但我认为这在技术上是正确的,但仍然是错误的。您正在使用所谓的两阶段构造。这两个阶段是:1)构建MyObject。 2)通过调用MyObject函数初始化Init()

难看。讨厌。容易出错和错误forgetfullness。语义错误,因为构造函数使对象处于完全初始化状态。作为一般规则,您应该不惜一切代价避免两阶段建设。更好的方法是在对象的构造函数中执行所有初始化 - 最好是在成员初始化列表中,但这对于聚合成员来说很难/不可能。在这些情况下,在构造函数体中初始化:

class MyClass
{
public:
  MyClass ()
  {
    array2D[10][10] = {0.0};
    logicalarray[2] = {false};
  }
  // ...
};

现在,构建MyObject也意味着MyObject初始化。毕竟,这就是构造函数的用途。那样做。

这里的问题是我们不能像这样初始化聚合。我们只能在构造时使用此语法初始化聚合,但这发生在(不存在的)初始化列表中。我们不能在C ++ 03中使用初始化列表来初始化聚合。所以你会留下一个丑陋的情况:

MyClass ()
{
  memset (logicalarray, logicalarray+2, 0);
  memset (array2D, array2D+sizeof (array2D), 0);
}

这引出了一个争论,你不应该首先使用原始数组,而是使用vector(或其他东西),并通过以下方式初始化它:

   class MyClass
    {
    public:
      std::vector <bool> mBools;
      std::vector <std::vector <double> > mDoubles;
      MyClass ()
      {
        std::fill_n (std::back_inserter (mBools), 2, false);
      }
    };

我会将mDoubles的初始化作为练习。