Link to home
Start Free TrialLog in
Avatar of LO19810527
LO19810527

asked on

static confusion

Could someone provide a GOOD explanation of what does the static keyword do to an object in a *.cpp file (outside of a function)?

Example:
//somefile.cpp file
#include “foo.h”
static foo Foo1;
foo Foo2;

How would the compiler treat Foo1 differently from Foo2?

Also, is there any way I can guarantee that Foo1 is initiated before any function inside somefile.cpp tries to use it?
ASKER CERTIFIED SOLUTION
Avatar of jkr
jkr
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of LO19810527
LO19810527

ASKER

But does the static keyword effect object duration?

For example, if you use the static keyword inside a function, that insures that the local static object stays the same between function calls.

Does this also relate to a global static object inside a *.cpp file?

>>>>You don't have to take care of that, the compiler
>>>>guarantees that.

This doesn't seem to be the case with the code that I've tested.
>>But does the static keyword effect object duration?

From my above comment:

"When modifying a variable, the static keyword specifies that the variable has static duration (it is
allocated when the program begins and deallocated when the program ends) and initializes it to 0 unless
another value is specified"

>>Does this also relate to a global static object inside a *.cpp file?

Yes.
>>>>You don't have to take care of that, the compiler
>>>>guarantees that.
>>This doesn't seem to be the case with the code that I've
>>tested.

The answer to this part of your question is not straightforward.

If you're object does not require the initialization of another object in another translation unit, then YES, the compiler will take care of proper initialization for you.

BUT, if your object does have dependencies on other objects in other translation units, then the compiler cannot guarantee proper initialization.

For more information, see Effective C++ by Scott Meyers (Item 47)
Axter,
>>BUT, if your object does have dependencies on other
>>objects in other translation units, then the compiler
>>cannot guarantee proper initialization.

Does that apply to both static objects and non-static objects?
When you say "translation units", does that mean *.cpp files?

jkr,
>>From my above comment:
>>"When modifying a variable, the static keyword specifies
>>that the variable has static duration (it is
>>allocated when the program begins and deallocated when
>>the program ends) and initializes it to 0 unless
>>another value is specified"
Doesn't the same happen to non-static global variables?
I'm sorry, but from your explanation, I don't understand what is the difference between using static and not using static on a global variable.
>>Does that apply to both static objects and non-static
>>objects?
Yes

>>When you say "translation units", does that mean *.cpp >>files?
Under general circustances, YES.  But is someone is silly enough to do an include "somefile.cpp", then the answer would be no.

>>what is the difference between using static
>>and not using static on a global variable.
Using static on a global variable, just puts the object at a file scope.
That means only objects in the file that has the static object, can access it directly.
>>I don't understand what is the difference between using static and not using static on a global variable

The other part of the above comment: "When modifying a variable or function at file scope, the static keyword
specifies that the variable or function has internal linkage (its name is not visible from outside the
file in which it is declared).""
>>The other part of the above comment: "When modifying a
>>variable or function at file scope, the static
>>keyword specifies that the variable or function has
>>internal linkage (its name is not visible from outside
>>the file in which it is declared).""

Is that the ONLY difference?
>>Is that the ONLY difference?

Yes. That's what Axter also described in the last part of his last comment.
>>Is that the ONLY difference?
Yes, that is the only difference.

I get the impression that you're having problems initializeing a global object, and you think that making it static will fix the problem.
If this is the case, then I hate to give you bad news, but making it static will not fix your problem.  The only thing static will do is put it into file scope.
You should probably note that using 'static' in this way is now not a recommended C++ feature (maybe actually officially deprecated, I can't remember) - you should use anonymous namespaces instead to achieve the same thing.

Unfortunately, as you are discovering, the keyword 'static' is a bit of a C++ wart - it (at least in appearance) means several different things in different contexts.
I checked, and this use of static is officially deprecated, (section D.2 of the standard).
>>I checked, and this use of static is officially deprecated, (section D.2 of the standard).

Yes, but the D.2 is referring to namespace scopes - not the global scope:

"The use of the static keyword is deprecated when declaring objects in namespace scope"
> Yes, but the D.2 is referring to namespace scopes
> - not the global scope:

I avoided mentioning that because, I believe it is confusing, but the sense of what I said is correct.

There is (if you read the standard) no such thing as 'global' scope any more - the top scoping level is 'namespace' scope, and anything that is not in any other namespace is in the special 'global namespace scope' - still a namespace scope.

However, I do think the standard is slightly confusing in this regard.
You mean 3.3.5(3)? Yes, It's getting confusing there...
The relevant section of the standard is section '3.3 Declarative regions and scopes'  and in particular section 3.3.5 Namespace Scope and this paragraph:

'A name declared outside all named or unnamed namespaces (7.3), blocks (6.3), function declarations
(8.3.5), function definitions (8.4) and classes (clause 9) has global namespace scope (also called global
scope). The potential scope of such a name begins at its point of declaration (3.3.1) and ends at the end of
the translation unit that is its declarative region. Names declared in the global namespace scope are said to
be global.'

there is no 'global' scope that is not also this special kind of 'namespace' scope.

Also, I meant to say unnamed namespaces and not 'anonymous namespaces' in my earlier comment.

> You mean 3.3.5(3)? Yes, It's getting confusing there...

Yes, I do (obviously now!), sorry I didn't see your comment when I posted my follow up.
>>Yes, but the D.2 is referring to namespace scopes - not >>the global scope:

IMHO, The standard is referring to using static with a namespace scope, and not a file scope/translation unit.

When static keywords is used with a global object inside a *.cpp file, it gives the object file scope, and NOT namespace scope.
> IMHO, The standard is referring to using static with a > namespace scope, and not a file scope/translation
> unit.

The problem is that according to the standard there is no such thing as 'global scope' or 'file scope'.  namespace scope is at the top of the scope 'tree'.  The only categories of scope that exist in C++ (according to the standard) are: Local scope, Function prototype scope, Function scope, Namespace scope and Class scope.

Check through the standard - you will find nothing whatever in there that refers to 'global' scope as anything other  than 'global namespace scope' - there is nothing in section 3.3 that refers to another kind of scope for global objects.

In any case, even if this use of static is not deprecated in the C++ standard (and I am fairly certain it is) - unnamed namespaces provide a much better and easier to understand way to achieve the same effect - hence the technique should be avoided in practise.
>>The problem is that according to the standard there is
>>no such thing as 'global scope' or 'file scope'.

They don't call it a file scope.  Instead it's called a translation unit.  That's why I posted both in my comments.
The standard does have translation unit.

>>unnamed namespaces provide a much better and easier to
>>understand way to achieve the same effect
>>- hence the technique should be avoided in practise.
>>unnamed namespaces provide a much better and easier to
>>understand way to achieve the same effect
>>- hence the technique should be avoided in practise.

That would give you the same effect as using static, but you still would have the same problem with initialization over multiple translation units.
So the main problem would not be fixed.
> The standard does have translation unit.

Absolutely it does, but it does not have 'translation unit' scope (or 'file scope').  'Translation Unit' scope is global namespace scope - and the use of 'static' in namespace scope is deprecated - look at my previous comment, there are no other kinds of scope apart from those I mentioned.

Unnamed namespaces do not solve the global initialisation problem - but then nothing will, if you have static data (in the other sense) that is cross-dependant at translation unit level, then you are asking for trouble.  I agree completely with this.

Unnamed namespaces do, however, provide a much clearer way of specifying data/functions/classes that are not visible outside a single source file (or translation unit).
>>and the use of 'static' in namespace scope is deprecated

After doing some checking, I think you're right about this aplying to file/global scope use.

>>but then nothing will, if you have
>>static data (in the other sense) that is cross-dependant
>>at translation unit level

One method you could use is to make the data static inside a function.
Example:

foo& GetSaticFoo(void)
{
 static foo Foo1;
 return Foo1;
}
A lot of good info here.

If you all don't mind, I'm going to split the points three way between jkr, Axter, and jasonclarke.
>>If you all don't mind

Certainly not :o)
I posted a reqest at the community support topic area.

Thanks for everyone's help.

I'm going to have to re-think my approach when using global objects.

I thought I was safe if I kept them in the cpp file with non extern, but I see that doesn't make a difference.
Points reduced to 75.  Now you can accept one expert comment as an answer.  After that, make questions for the ther experts for 75 points in this topic area.

Thank you
Computer101
E-E Moderator
Axter and jasonclarke,
I posted a 75 point question for each of you.

Thank you!
Thanks.