6

我有一个奇怪的问题,

在 A 类中声明一个名为 B 类的静态成员变量。并在cpp文件中初始化。但是 B 类的构造函数从未被调用过。我尝试使用一些小测试,可以正常调用测试构造函数。所以这对我们的生产系统来说很奇怪。

像这样的代码,在hpp中:

class Test
{
    public:
    Test()
    {
        ofstream file("/tmp/wup.txt",ios::app);
        file << "wup in test" << endl;
        file.close();
    }
};

//## An extended personality
class TsdNAExtPersonality : public TsdNAPersonality{
public:

  TsdNAExtPersonality(
        s_gg62_personRec * gg62Header,
                   TsdNAFunctionType requiredFunctionType);
private:
  static Test test;

public:
  TsdNAExtPersonality( string * personalityFile, TsdNAFunctionType requiredFunctionType);
};

在另一个cpp文件中我初始化

Test TsdNAExtPersonality::test;

我尝试了几种方法,但我发现所有方法都没有用。

  1. 没有将变量设置为成员变量而是全局变量 ==> 也无法输出
  2. 将成员变量更改为指针并将初始化方式更改为使用 new ==> no

环境是HP-UX,编译是aCC

所以我的问题是:

  1. 是否有任何编译选项会影响变量?换句话说,所有的静态变量都不会被初始化。

  2. 从 C++ 的标准来看,应该在加载库时调用它,对吧?

  3. 我用同样的方法放了另一个静态int值,它可以被初始化。但是没有调用类构造函数,很奇怪。

  4. 我的代码有什么错误吗?

4

4 回答 4

8

从 C++ 的标准来看,应该在加载库时调用它,对吧?

不会。具有静态存储持续时间的对象的动态初始化保证在执行同一翻译单元中定义的任何函数之前发生。如果没有这样的函数,或者你的程序从不调用它们,那么就不能保证它会被初始化。

我用同样的方法放了另一个静态int值,它可以被初始化。但是没有调用类构造函数,很奇怪。

一个int变量在程序启动之前被静态初始化,只要它的初始化器是常量。

是否有任何编译选项会影响变量?

我不知道,但我不熟悉你的平台。您可以通过在函数中确定对象的范围来更好地控制对象的创建:

static Test & test() {
    static Test test;
    return test;
}

现在保证在第一次调用该函数时进行初始化。当然,您需要记住在某个时候调用它。

于 2013-09-13T16:31:12.057 回答
1

C++ 程序的启动和关闭有点像灰色区域,因为不清楚您已经可以使用多少代码(因为它已被初始化)以及还有多少代码正在启动。在关闭时析构函数也会发生同样的情况......目前尚不清楚当您的静态实例被破坏时有多少子系统已经关闭。

此外,您永远不应该对可能失败的任何事情使用静态初始化,在开始之前或结束之后进行调试main可能非常困难。

另请注意,未定义初始化静态的顺序(除了相对于同一编译单元中的其他静态),它可能会从一个编译更改为下一个编译。这意味着您可能对工作程序感到满意,直到由于某种奇怪的原因您得到不同的初始化顺序并且事情停止工作而没有对代码进行任何相关更改。

对极其简单的事情使用静态初始化是可以的,因为其他任何事情都不是,你应该做适当的受控初始化。

于 2013-09-13T16:33:00.233 回答
0

C++ 中的静态初始化是:

  • 零初始化
  • 常量初始化
  • 动态初始化

因此,您最好的选择是在第一次函数调用时进行初始化:

int fn() {
    static int result = 42;
    return result;
}

编辑

如果要在 main 之前初始化:

struct Initialize { 
    Initialize() { fn(); }
}

Initialize initialize;
于 2013-09-13T16:32:22.283 回答
0

我认为您的编译器中存在错误。

在 linux/g++ 上运行这个简单的代码可以得到预期的结果:

#include <iostream>

using namespace std;

class A
{
    public:
        A() { cout << "Hallo" << endl; }
};

class B
{
    public:
    static A a;
};

A B::a;    // < here the constructor must be called!

int main()
{
   cout << "Main runs" << endl;
   return 0;
}

结果是:

Hallo
Main runs

构造静态数据成员时必须调用构造函数(上面的注释行)。

于 2013-09-13T16:50:13.963 回答