Re: "static" objects and functions
On Jun 1, 10:43 pm, James Kanze <james.ka...@gmail.com> wrote:
On May 31, 4:17 pm, Jess <w...@hotmail.com> wrote:
On May 31, 8:01 pm, James Kanze <james.ka...@gmail.com> wrote:
jeffjohnson_al...@yahoo.com wrote:
I learned that there are five kinds of static objects, namely
1. global objects
2. object defined in namespace scope
3. object declared static instead classes
4. objects declared static inside functions (i.e. local static
objects)
5. objects declared at file scope.
I have seen the examples of (3) and (4) above, can someone please give
me some examples and their purpose for the other types of static
objects?
For some reason, Google won't let me read your original posting,
so I'll answer here...
What do you mean by "static objects": objects declared with the
keyword static, or objects with static lifetime. The two are
only vaguely related, and you can also use the keyword static to
declare functions. For historical reasons, the keyword static
is overloaded, and depending on context, it affects both object
lifetime and linkage. Roughly speaking:
-- At namespace scope, the keyword static means that the symbol
being defined has internal linkage, rather than external
(which is the default at namespace scope). All objects
declared at namespace scope (with or without the keyword
static) have static lifetime. (Lifetime is irrelevant with
regards to functions.)
Many thanks for your answers. :) There're still a few issues that
bother me. Although, as you've said, static under namespace is
deprecated, I feel not so comfortable if I don't completely understand
it. :) If I have
namespace N{
A a;
}
then "a" has external linkage, but if I have
namespace N{
static A a;
}
then "a" has internal linkage, is this right?
Correct.
I think "internal linkage" means it's only accessible within
this current translation unit, is this also right?
Not really. Although it's common to think of it in such terms,
linkage is really concerned with whether two (fully qualified)
names refer to the same object (or function, or class, or
whatever). In the above, the fully qualified name is N::a, and
the name is "accessible" in any translation unit which declares
it. In the first case, it has external linkage, which means
that all of the names N::a refer to the same, unique object,
regardless of which translation unit they are in. In the
second, with the static, the name as internal linkage: all of
the declarations within a single translation unit refer to the
same, unique object, but each translation unit has a different
object.
Furthermore, I tried one example as follows:
//test.h
class A{
public:
int x;
A():x(10){}
};
namespace foo{
static extern A b;
Did this compile? It shouldn't: both static and extern are
"storage class specifiers", and "At most one
storage-class-specifier shall appear in a given
decl-specifier-seq."
}
//test.cpp
#include "test.h"
namespace foo{
A b;
};
//testT.cpp
#include<iostream>
#include "test.h"
using namespace std;
int main(){
cout << foo::b.x << endl;
return 0;
}
However, the compiler error was
"multiple storage classes in declaration of 'b'"
What does this mean?
Exactly what it says. The keywords "auto", "register",
"static", "extern" and "mutable" are storage class specifiers,
and the standard says that at most one can appear in any given
declaration.
Formally, this is a purely syntactic restriction, but the
motivation is that in general, the semantics of each of these
keywords conflict. (One could argue about auto and register, I
suppose.) In this particular case, "static" says that the
variable has internal linkage, and "extern" says that it has
external linkage. Extern also says that it is only a
declaration, and not a definition. The C++ declaration syntax
just grew, and isn't always as coherent or as logical as one
might like. Thus:
namespace A {
int a1 ; // external linkage, definition.
extern int a2 ; // external linkage, declaration.
static int a3 ; // internal linkage, definition.
int const a4 ; // *internal linkage, definition.
extern int const a5 ; // external linkage, declaration.
static int const a6 ; // *internal linkage, definition.
int i1 = 42 ; // external linkage, definition.
extern int i2 = 42 ; // external linkage, definition!
static int i3 = 42 ; // internal linkage, definition.
int const i4 = 42 ; // internal linkage, definition.
extern int const i5 = 42 ; // external linkage, definition.
static int const i6 = 42 ; // internal linkage, definition.
}
The declarations marked * are in fact illegal, as a definition
of a const object is illegal unless the object either has a
non-trivial constructor or an initializer. Note that the table
is full of incoherences and oddities---note in particular the
role of const (which logically is completely orthogonal), and
the fact that an initialization forces the declaration to be a
definition, even if it is extern. (And that to define a const
object with external linkage, you have to use extern.)
Thank you so much for giving me these examples. :) There are really
so many incoherences, headache...Moreover, about the requirement on
"const" ("const object is illegal unless the object either has a non-
trivial constructor or an initializer"), is it universal or is it only
applicable when it's within a namespace?
Also, these declarations suppose that the object has not been
previously declared. Something like:
namespace A {
static int const x = 42 ;
extern int const x ;
}
is perfectly legal---linkage is established by the first
declaration, and cannot be changed later, and extern only means
external linkage if there has been no previous declaration. On
the other hand, inversing them is not---static means internal
linkage, always, so the linkages conflict.
-- At class scope, static means that the object or function is
independant of any instance of the class. All symbols
declared at class scope have external linkage; objects
declared with static have static lifetime (as opposed to a
lifetime linked to that of the containing instance of the
class type).
-- At local scope, only objects (not functions) can be declared
static; such objects have static lifetime. (All objects
declared at local scope, unless explicitly declared extern,
have no linkage. Functions declared at local scope always
have external linkage.)
The only local scope that I've seen is within a function body, is
there any other kind of local scope?
Local scope is always within a function body, or more exactly, a
compound statement (but a compound statement can only
occur within a function body).
How can a function be declared within such local scope?
void
f()
{
std::vector< int > v( std::istream_iterator< int >( file ),
std::istream_iterator< int >() ) ;
}
:-). The problem is more often, how can we ensure that a
definition is not a function declaration in local scope; in the
above, the programmer probably wanted to define a local variable
v, using the two iterator constructor of vector. In fact, he has
declared a function (with external linkage, in global scope)
taking two arguments, and istream_iterator<int>, and a pointer
to a function returning and istream_iterator<int>, and returning
a vector<int>.
Why is above a declaration? It doesn't look like a definition either.
To me, it looks like calling the function "v": the first argument
passed to "v" is an iterator (constructed from "file") and the second
argument is also an iterator, constructed by the default
constructor.
On the other hand, the intent of:
void
f()
{
extern double g( double ) ;
// ...
}
seems quite clear, although it's not the sort of thing one would
encourage.
By the way, I think "no linkage" means it is only accessible
within that local scope where it's defined, is this correct?
No linkage means that no other declaration can refer to the
object in question. For example:
void
f()
{
int a ; // No linkage...
{
int a ; // So this can't be the same variable.
// ...
}
}
There's an interesting (perverse?) example of this in the
standard:
static int i ; // 1.
void g()
{
int i ; // 2. Hides the static 1.
{
extern int i ; // 3.
}
}
The line labeled 3 refers to yet a third object (not defined
here): since the declaration at 2 hides the declaration at 1,
the compiler doesn't "see" it, and since the declaration at 2
has no linkage, the declaration at 3 declares a new object, with
external linkage (different from the object with internal
linkage defined at 1).
I can see that declaration at line 2 hides declaration at 1. I think
"i" at line 2 is also a definition, which is visable to inner block
(i.e. line 3). Therefore, I think line 3 is saying declare the "i" at
line 2 as external. I thought in general, objects declared at outer
block are always visible in the inner blocks, unless there's a re-
declaration/definition of it in the inner blocks, is this wrong?
(And if you aren't thoroughly confused yet, you should be.)
I am thoroughly confused, as you've correctly guessed... :(
Thanks,
Jess