【问题标题】:Need to programmatically initialise class variable array, how best do I do it?需要以编程方式初始化类变量数组,我该怎么做?
【发布时间】:2011-08-23 20:06:58
【问题描述】:

在 C++ 中,我有一个双精度数组,需要在运行时以编程方式初始化一次,以便整个班级共享。它们既可以是静态的,也可以是恒定的。我怎样才能最好地初始化它们?随着并行处理器的普及,我已经开始使用静态了。那么我是否必须设置一个标志来运行一次,或者是否有一些静态 const 魔法将它们初始化为函数(好的)或类(也可以)的局部变量?

    double sumOfWeights = 0.0;
    double fracObs = 0.0;
    for (int i = 0; i < NUMTRACES; i++) {
        double weightAtI = SQUARED(1 - SQUARED(MAXTRACEWRTMIDTRACE * (MIDTRACE - i)
                                        / double(MIDTRACE)));
        sumOfWeights += weightAtI;
        fracObs += obsArray[i] * weightAtI;
    }
    return fracObs / sumOfWeights;

在上面的代码中,我想对 weightAtI 进行查找,每个双精度都已经除以 sumOfWeights,这样我就可以在不遍历 NUMTRACES 的情况下检索它们。

_编辑_ 没关系,这就是构造函数的用途:) 只是希望解决我的静态、常量和初始化问题。谢谢赛斯

_编辑_ 不确定这是否是我想要的效果。构造函数在每个实例上运行,即使成员是静态的,不是吗?不,让我看看...

_编辑_ 我认为最有效的解决方案是在构造函数中用静态标志保护初始化循环。作为一个 POD 标志,我确信它的行为应该是适当的,我只是不太确定现阶段是什么。

_编辑_ 啊,明白了:

class X
{
public:
    static int i;
};
int X::i = 0; // definition outside class declaration

_编辑_ 不幸的是,当涉及到我的代码时,

    static const int MIDTRACE = 3;
    static const int NUMTRACES = 2 * MIDTRACE + 1;
    static double WEIGHTATI[NUMTRACES];

我收到链接器错误:

meobj.obj : error LNK2020: unresolved token (0A00001C) "private: static double * mens:meclass::PIMPL::WEIGHTATI" (?WEIGHTATI@PIMPL@meclass@mens@@$$Q0PANA) meobj.obj:错误 LNK2001:无法解析的外部符号“私有:静态双精度 * mens:meclass::PIMPL::WEIGHTATI”(?WEIGHTATI@PIMPL@meclass@mens@@$$Q0PANA)

由于我的构造函数:

meclass::PIMPL() {
    if (!doneStaticInit) {
        double sumOfWeights = 0.0;
        for (int i = 0; i < NUMTRACES; i++) {
            WEIGHTATI[i] = SQUARED(1 - SQUARED(MAXTRACEWRTMIDTRACE * (MIDTRACE - i) / double(MIDTRACE)));
            sumOfWeights += WEIGHTATI[i];
        }
        for (int i = 0; i < NUMTRACES; i++) WEIGHTATI[i] /= sumOfWeights;
        doneStaticInit = true;
    }
}

【问题讨论】:

  • 似乎是显式的并且没有以编程方式初始化。
  • +1 是因为并行处理器的惊人普及目前普遍存在。
  • 目前流行的并行处理器数量惊人?!请告诉我你是故意写的!

标签: c++ arrays static initialization constants


【解决方案1】:

初始化 => 构造函数。一次 => 静态实例。所以一种方法是使用构造函数的静态实例。

#include <iostream>

struct Foo
{
    Foo()
    {
        std::cout << "Initializing them values..." << std::endl;
        for( int i = 0;  i < 3;  ++i )
        {
            values[i] = i;
        }
    };

    int values[3];
};

void doThings()
{
    static Foo const    foo;        // Is initialized ONCE.

    for( int i = 0;  i < 3;  ++i )
    {
        std::cout << foo.values[i] << " ";
    }
    std::cout << std::endl;
}

int main()
{
    doThings();
    doThings();
    doThings();
}

干杯,

【讨论】:

  • 这几乎就是我编辑的内容,如果网站没有拒绝它,____EDIT____ 没关系,这就是构造函数的用途 :) 只是希望将我的静态、常量和初始化 gremlins 处理成讨价还价。
  • 在构造函数中做它的事情是它会在每次实例化时重新初始化。此外,您还没有将您的/我的数组声明为静态的,因此或以其他方式您的解释“Once => static instance”是,恕我直言,留下想要的。抱歉,如果您认为我想要一个用于静态使用的类,我必须更清楚地说明这一点。
  • @John:我更改了代码以使其更清晰。在原始代码和当前代码中,foo 是静态的、const 的并且被初始化一次。但是如果你运行这个新代码,你可以看到它只初始化了一次。
  • @John:你的第一句话是错误的。你的第二句话是错误的。你的第三句话,我不明白,我认为它没有意义。
  • 其中的 cpp 文件刚刚经过 PIMPL 处理,并且已经包含至少 4 个私有内部类或结构。任何方式我都可以在包含对象的构造函数中创建一个双重初始化一次的 POD 数组?
【解决方案2】:

您可以在构造函数中放置static bool 标志。该标志只会在第一次被调用时初始化为false。之后它将保持真实。

// foo.h

class Foo {
  static const int MIDTRACE = 3; // static const, no definition needed
  static const int NUMTRACES = 2 * MIDTRACE + 1; // static const, no definition needed
  static double WEIGHTATI[NUMTRACES]; // not const, so need definition outside of class
public:
  Foo() {
    static bool array_initialized = false;
    if( !array_initialized ) {
      // Initialize array
      array_initialized = true;
    }
  }
  // Other members
};

在源文件中,而不是头文件中:

// foo.cpp
include "foo.h"
double Foo::WEIGHTATI[NUMTRACES];

【讨论】:

  • 我将如何初始化双精度的静态数组?我收到错误(显示在更新的 OP 中)。一切似乎都需要显式初始化并阻碍程序化初始化。
  • 你仍然需要在你的类之外的源文件中定义你的static double WEIGHTATI[NUMTRACES]double meclass::WEIGHTATI[NUMTRACES];。你的构造函数应该和类同名:meclass::meclass().
  • PIMPL 是一个子类,meclass 只是一个包装器。 double meclass::WEIGHTATI[NUMTRACES]; 是声明而不是定义。?由于这就是正文中的全部内容,因此我将它们作为非成员变量放在了顶部。
  • 任何非常量静态成员变量都应该在类中声明,并在类外定义一次。并且子类不能访问超类中的私有变量,因此需要对其进行保护。
  • 这里的第二条评论有效并且使代码更优雅。谢谢约翰PS
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-11
  • 1970-01-01
  • 2021-02-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多