简体   繁体   中英

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?

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.

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.)

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).

And, to make this more interesting, albeit being C++ this is not to be used in object-oriented but in procedural code. So please no answers proposing objects or classes. Just imagine it to be C with the syntax of 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...

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. 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).

And of course, something in the code will have to call initHelpMe too, so it may turn out to be the same anyway.

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. After that the initialization of unit B resets _initData back to zero and may produce a memory leak or other harm.

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. I've coded both ways. It comes down to the SW architecture.

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.

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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