通过使用(稍微)全局变量与静态函数变量的初始值?

时间:2013-08-23 10:27:40

标签: c++ c static initialization global-variables

我在整个代码中都需要一些小辅助函数。 要工作,需要使用一些数据进行初始化。 我应该在哪里存储init数据?

我提出了两种方法:

我在helper.cpp文件的范围内创建静态变量,我使用专用的setter函数设置它,然后在我的帮助函数中使用。

static int _initData = 0;

void initHelpMe(int initData)
{
    _initData = initData;
}

void helpMe()
{
    doSomethingWith(_initData);
}

或者我在原始辅助函数中使用静态函数变量,并使用默认参数。

void helpMe(int initData = 0)
{
    static int _initData = 0;
    if (initData != 0)
        _initData = initData;

    doSomethingWith(_initData);
}

(假设0在initData的有效数据范围之外,并且我没有显示额外的代码,以确保首次调用该函数时引发错误而不首先启动它。)

这两种方法有哪些优点/缺点,是否有更好的方法呢?

我当然喜欢第二种方法,因为它将所有功能保存在一个地方。但我已经知道它不是线程安全的(这不是问题a.t.m。)。

并且,为了使这更有趣,尽管是C ++,但这不是用于面向对象而是用于程序代码。所以请不要提出建议对象或类的答案。想象一下,它是C语言的C语言。

3 个答案:

答案 0 :(得分:1)

我打算建议你将数据包装到一个对象中,直到我意识到你要求一个带有C ++标签的C解决方案......

您的两种解决方案都有其优势。

第二个是我最喜欢的一个,假设我们只是过去看看/可维护性"。但是,如果使用helpMe多次调用initData == 0,则存在一个缺点,因为额外的if在第一种情况下不存在。如果doSomethingWith()足够长的函数和/或编译器能够内联helpMe(并且initData是常量),这可能是也可能不是问题。

当然,代码中的某些内容也必须调用initHelpMe,因此无论如何它可能会变得相同。

总结:首选基于隔离/封装的第二个。

答案 1 :(得分:1)

我显然更喜欢第二个!不同编译单元中的全局静态数据以未指定的顺序初始化(尽管在一个单元中)。首次调用时初始化函数的本地静态数据。

示例

如果你有两个翻译单元A和B.单元A在初始化期间调用单元B的功能helpMe。假设初始化顺序是A,B。 第一个解决方案将零初始化_initData设置为某个initData。之后,单元B的初始化将_initData重置为零,并可能产生内存泄漏或其他危害。

还有第三种解决方案:

void helpMe(int initData = 0)
{
    static std::once_flag once;
    static int _initData = 0;
    std::call_once(once, [&] {
        _initData = initData;
    }
    doSomethingWith(_initData);
}

答案 2 :(得分:0)

我有两种感觉。

首选隔离选项2,但选项1适合移植到C ++类。我已经编码了两种方式。它归结为SW架构。

让我提出另一点。

两个选项都在下方:您没有限制初始化为一次。 “需要用一些数据进行初始化”。 OP的条件似乎确保正确初始化initHelpMe(123)HelpMe(123)后跟helpMe(),但不会阻止/检测二次初始化。

如果需要防止/检测到辅助,可以使用一些额外的代码。

// Initialization 
if (_initData != 0) {
  ; // Handle error
}
_initData = initData;

我使用的另一种范例如下。它可能无法在您的代码中实现,因为它不会将initData作为参数传递,但会神奇地可以获取它。

void helpMe(void) {
  static int Initialized = 0;
  if (!Initialized) {
    Initialized = 1;
    _initData = initData();
  }
  doSomethingWith(_initData);
}