简体   繁体   English

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

[英]Init values by using (somewhat) global variables vs. static function variables?

I have some small helper functions needed throughout the code. 我在整个代码中都需要一些小辅助函数。 To work, they need to be initialized with some data once. 要工作,需要使用一些数据进行初始化。 Where should I store the init data? 我应该在哪里存储init数据?

I've come up with two methods: 我想出了两种方法:

I create static variables in the scope of the helper.cpp file which I set with a dedicated setter function and then use in my helper function. 我在helper.cpp文件的范围内创建静态变量,我使用专用的setter函数设置它,然后在我的帮助函数中使用。

static int _initData = 0;

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

void helpMe()
{
    doSomethingWith(_initData);
}

Or I use a static function variable inside the original helper function and a default parameter to it. 或者我在原始辅助函数中使用静态函数变量,并使用默认参数。

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

    doSomethingWith(_initData);
}

(Lets asume that 0 is outside of the valid data range of initData and that I've not shown additional code to ensure an error is raised when the function is called for the first time without initiating it first.) (假设0在initData的有效数据范围之外,并且我没有显示额外的代码,以确保首次调用该函数时引发错误而不首先启动它。)

What are the advantages / disadvantages of those two methods and is there an even better way of doing it? 这两种方法有哪些优点/缺点,是否有更好的方法呢?

I of course like the second method, because it keeps all the functionality in one place. 我当然喜欢第二种方法,因为它将所有功能保存在一个地方。 But I already know it is not thread-safe (which is not an issue atm). 但我已经知道它不是线程安全的(这不是一个问题atm)。

And, to make this more interesting, albeit being C++ this is not to be used in object-oriented but in procedural code. 并且,为了使这更有趣,尽管是C ++,但这不是用于面向对象而是用于过程代码。 So please no answers proposing objects or classes. 所以请不要提出建议对象或类的答案。 Just imagine it to be C with the syntax of C++. 想象一下,它是C语言的C语言。

I was going to suggest that you wrap your data into an object, until I realized that you are asking for a C solution with a C++ tag... 我打算建议你将数据包装到一个对象中,直到我意识到你要求一个带有C ++标签的C解决方案......

Both of your solutions have their benefits. 您的两种解决方案都有其优点。

The second one is the one I'd prefer, assuming we just go by "what it looks like/maintainability". 第二个是我更喜欢的,假设我们只是“看起来像什么/可维护性”。 However, there is a drawback if helpMe is called MANY times with initData == 0 , because of the extra if , which isn't present in the first case. 但是,如果使用initData == 0多次调用helpMe ,则存在一个缺点,因为在第一种情况下不存在额外的if This may or may not be an issue if doSomethingWith() is long enough a function and/or the compiler has the ability to inline helpMe (and initData is constant). 如果doSomethingWith()足够长的函数和/或编译器能够内联helpMe (并且initData是常量),这可能是也可能不是问题。

And of course, something in the code will have to call initHelpMe too, so it may turn out to be the same anyway. 当然,代码中的某些东西也必须调用initHelpMe ,所以无论如何它可能会变成相同的。

In summary: Prefer the second one, based on isolation/encapsulation. 总结:首选基于隔离/封装的第二个。

I clearly prefer the second! 我显然更喜欢第二个! Global static data in different compilation units are initialized in unspecified order (In one unit in order, though). 不同编译单元中的全局静态数据以未指定的顺序初始化(尽管在一个单元中)。 Local static data of a function is initialized at first call. 首次调用时初始化函数的本地静态数据。

Example : 示例

If you have two translation units A and B. The unit A calls during initialization the function helpMe of unit B. Assume the order of initialization is A, B. The first solution will set the zero initialized _initData to some initData. 如果你有两个转换单元A和B.单元A在初始化期间调用单元B的函数helpMe。假设初始化的顺序是A,B。第一个解决方案将零初始化_initData设置为某个initData。 After that the initialization of unit B resets _initData back to zero and may produce a memory leak or other harm. 之后,单元B的初始化将_initData重置为零,并可能产生内存泄漏或其他危害。

There is a third solution: 还有第三种解决方案:

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

I feel strongly both ways. 我有两种感觉。

Prefer option 2 for the isolation, but option 1 lends itself to porting to a C++ class. 首选隔离选项2,但选项1适合移植到C ++类。 I've coded both ways. 我已经编码了两种方式。 It comes down to the SW architecture. 它归结为SW架构。

Let me offer another point. 让我提出另一点。

Both options down side: You have not limited initialization to one occurrence. 两个选项都在下方:您没有初始化限制为一次。 "need to be initialized with some data once". “需要用一些数据进行初始化”。 It appears OP's conditions insure a proper initialization of initHelpMe(123) or HelpMe(123) followed by helpMe() , but do not prevent/detect a secondary initialization. OP的条件似乎确保initHelpMe(123)HelpMe(123)的正确初始化,然后是helpMe() ,但不要阻止/检测二次初始化。

Should a secondary need to be prevented/detected, some additional code could be used. 如果需要防止/检测到辅助,则可以使用一些附加代码。

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

Another paradigm I've used follows. 我使用的另一种范例如下。 It may not be realizable in you code as it does not pass initData as a parameter but magically can get it. 它可能无法在您的代码中实现,因为它不会将initData作为参数传递,但神奇地可以获得它。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM