简体   繁体   中英

Any risk of sharing local static variable of a method between instances?

Let's say I create:

class Hello {
    public:
        int World(int in)
        {
            static int var = 0;    // <<<< This thing here.
            if (in >= 0) {
                var = in;
            } else {
                cout << var << endl;
            }
        }
};

Now, if I do:

Hello A;
Hello B;

A.World(10);
A.World(-1);
B.World(-1);

I'm getting output of "10" followed by another "10". The value of the local variable of a method just crossed over from one instance of a class to another.

It's not surprising - technically methods are just functions with a hidden this parameter, so a static local variable should behave just like in common functions. But is it guaranteed ? Is it a behavior enforced by standard, or is it merely a happy byproduct of how the compiler handles methods? In other words - is this behavior safe to use? (...beyond the standard risk of baffling someone unaccustomed...)

Yes. It doesn't matter if the function is a [non-static] member of a class or not, it's guranteed to have only one instance of it's static variables.

Proper technical explanation for such variables is that those are objects with static duration and internal linkage - and thus those names live until program exits, and all instances of this name refer to the same entity.

Just one thing to add to the correct answer. If your class was templated, then the instance of var would only be shared amongst objects of the same instantiation type. So if you had:

template<typename C>
class Hello {
    public:
        int World(int in)
        {
            static int var = 0;    // <<<< This thing here.
            if (in >= 0) {
                var = in;
            } else {
                cout << var << endl;
            }
        }
};

And then:

Hello<int> A;
Hello<int> B;
Hello<unsigned> C;

A.World(10);
A.World(-1);
B.World(-1);
C.World(-1);

Then the final output would be "0" rather than "10", because the Hello<unsigned> instantiation would have its own copy of var .

If we are talking about the Windows Compiler it's guaranteed

https://msdn.microsoft.com/en-us/library/y5f6w579.aspx

The following example shows a local variable declared static in a member function. The static variable is available to the whole program; all instances of the type share the same copy of the static variable.

They use an example very similar to yours.

I don't know about GCC

Yes, it is guaranteed. Now, to answer the question "Any risk of sharing local static variable of a method between instances?" it might be a bit less straightforward. There might be potential risks in the initialization and utilization of the variable and these risks are specific to variables local to the method (as opposed to class variables).

For the initialization, a relevant part in the standard is 6.7/4 [stmt.dcl]:

Dynamic initialization of a block-scope variable with static storage duration (3.7.1) or thread storage duration (3.7.2) is performed the first time control passes through its declaration; such a variable is considered initialized upon the completion of its initialization. If the initialization exits by throwing an exception, the initialization is not complete, so it will be tried again the next time control enters the declaration. If control enters the declaration concurrently while the variable is being initialized, the concurrent execution shall wait for completion of the initialization. If control re-enters the declaration recursively while the variable is being initialized, the behavior is undefined.

In the simple cases, everything should work as expected. When the construction and initialization of the variable is more complex, there will be risks specific to this case. For instance, if the constructor throws, it will have the opportunity to throw again on the next call. Another example would be recursive initialization which is undefined behavior.

Another possible risk is the performance of the method. The compiler will need to implement a mechanism to ensure compliant initialization of the variable. This is implementation-dependent and it could very well be a lock to check if the variable is initialized, and that lock could be executed every time the method is called. When that happens, it can have a significant adverse effect on performance.

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