473,756 Members | 4,165 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

"static" objects and functions

Hello,

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?

Moreover, I've seen an extern statement:

class A{...};
extern A a;

which is said to be a definition for static object "a". Why is this a
static object without "static" keyword?

In addition to static objects, there are static functions. I think a
static member function, such as

class A{
static void f();
};
means it doesn't require any instance of A, and can operate on class
A. Is this right? Then I'm wondering if there's any static non-
member function, and if there is, when is it good to use it?

The example "extern A a" above also raises another question. Should I
regard it as a declaration that says there's an object "a" defined in
another source file, or, shall I regard it as a definition, since its
default constructor may be called?

Many thanks,
Jess

May 30 '07
14 6023
On Jun 1, 10:43 pm, James Kanze <james.ka...@gm ail.comwrote:
On May 31, 4:17 pm, Jess <w...@hotmail.c omwrote:
On May 31, 8:01 pm, James Kanze <james.ka...@gm ail.comwrote:
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<iostre am>
#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...More over, 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_it erator< int >( file ),
std::istream_it erator< 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_iterato r<int>, and a pointer
to a function returning and istream_iterato r<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

Jun 2 '07 #11
On Jun 2, 4:04 pm, Jess <w...@hotmail.c omwrote:

[...]
Thank you so much for giving me these examples. :) There are really
so many incoherences, headache...More over, 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?
It's universal, but it applies (obviously, if you think about
it) when the object is created, not when it is declared. So:

struct Toto
{
int const titi ; // No initializer here...
Toto() ;
} ;

Toto::Toto()
: titi( 42 ) // initializer required here...
{
}

There is a special case for const static members of integral
type; the initializer can appear in the declaration (in the
class definition) rather than in the definition of the object.

[...]
How can a function be declared within such local scope?
void
f()
{
std::vector< int v( std::istream_it erator< int >( file ),
std::istream_it erator< 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_iterato r<int>, and a pointer
to a function returning and istream_iterato r<int>, and returning
a vector<int>.
Why is above a declaration?
Because the standard says that if something can be interpreted
as a declaration, it is. Both of the sub-expressions
"std::istream_i terator< int >( file )" and
"std::istream_i terator< int >()" can be interpreted as
declarations. And if they are declarations, then the result is
the declaration of a function. To make it clearer, replace the
complicated type names with simple symbols: A for
"std::vecto r< int >", and B for "std::istream_i terator< int >":

A v( B (file), B() ) ;

Now, remove the superfluous parentheses, and rewrite the second
declaration according to the special rules which apply to
function parameters, and you get:

A v( B file, B (*)() ) ;

Which looks very much like a function declaration, a function v
taking two arguments, a B, and a pointer to a function returning
a B, and returning an A.
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.
And what does the "std::vecto r< int >" do in the statement? If
a statement starts with the name of a type, and that name is not
immediately followed by a '(', it's either a declaration of some
sort, or completely illegal. (If the name of the type is
immediately followed by a '(', it might still be a declaration.
Or it might not be, depending on what follows.)

[...]
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).
That's correct so far.
Therefore, I think line 3 is saying declare the "i" at
line 2 as external.
That would be logical, and it would be logical (IMHO) for the
above to be an error, since there are conflicting linkage
specifications. According to the standard, however, the "i" in
line 2 has no binding, so no other declaration can refer to it.
Thus, since line 3 can't refer to it, and line 1. isn't visible
at this point, line 3 declares still another i.

Whether you or I think that this is a good idea, or the way it
should be, is irrelevant. The above example is taken directly
from the standard.
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... :(
Well, you seemed to want to know all of the details. And they
are confusing. I've written compilers in the past, and worked
with language standards for something like 20 years, and I still
have to go very, very slowly when attacking this in C++. (And
if you think that this is confusing, wait until you attack
function overload resolution, or name binding in templates.)

--
James Kanze (Gabi Software) email: ja*********@gma il.com
Conseils en informatique orientée objet/
Beratung in objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Jun 3 '07 #12
On Jun 4, 3:19 am, James Kanze <james.ka...@gm ail.comwrote:
On Jun 2, 4:04 pm, Jess <w...@hotmail.c omwrote:

[...]
Thank you so much for giving me these examples. :) There are really
so many incoherences, headache...More over, 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?

It's universal, but it applies (obviously, if you think about
it) when the object is created, not when it is declared. So:

struct Toto
{
int const titi ; // No initializer here...
Toto() ;
} ;

Toto::Toto()
: titi( 42 ) // initializer required here...
{
}

There is a special case for const static members of integral
type; the initializer can appear in the declaration (in the
class definition) rather than in the definition of the object.

[...]
How can a function be declared within such local scope?
void
f()
{
std::vector< int v( std::istream_it erator< int >( file ),
std::istream_it erator< 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_iterato r<int>, and a pointer
to a function returning and istream_iterato r<int>, and returning
a vector<int>.
Why is above a declaration?

Because the standard says that if something can be interpreted
as a declaration, it is. Both of the sub-expressions
"std::istream_i terator< int >( file )" and
"std::istream_i terator< int >()" can be interpreted as
declarations. And if they are declarations, then the result is
the declaration of a function. To make it clearer, replace the
complicated type names with simple symbols: A for
"std::vecto r< int >", and B for "std::istream_i terator< int >":

A v( B (file), B() ) ;

Now, remove the superfluous parentheses, and rewrite the second
declaration according to the special rules which apply to
function parameters, and you get:

A v( B file, B (*)() ) ;

Which looks very much like a function declaration, a function v
taking two arguments, a B, and a pointer to a function returning
a B, and returning an A.
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.

And what does the "std::vecto r< int >" do in the statement? If
a statement starts with the name of a type, and that name is not
immediately followed by a '(', it's either a declaration of some
sort, or completely illegal. (If the name of the type is
immediately followed by a '(', it might still be a declaration.
Or it might not be, depending on what follows.)

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

That's correct so far.
Therefore, I think line 3 is saying declare the "i" at
line 2 as external.

That would be logical, and it would be logical (IMHO) for the
above to be an error, since there are conflicting linkage
specifications. According to the standard, however, the "i" in
line 2 has no binding, so no other declaration can refer to it.
Thus, since line 3 can't refer to it, and line 1. isn't visible
at this point, line 3 declares still another i.
Thanks again. My email yesterday seemed to be deleted by google...
I'm still wondering why "i" at line2 is visible at line3, but there's
no binding for the "i" at line 2. No binding means no linkage, is
this correct? If so, is it completely useless to declare "i" at line
2? If I have another line after line 2, but before the "{" above line
3

cout << i << endl;

then I think "i" at line 2 gets printed. Does it mean the "{" above
line 3 makes "i" at line 2 have no binding?

>
Whether you or I think that this is a good idea, or the way it
should be, is irrelevant. The above example is taken directly
from the standard.
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... :(

Well, you seemed to want to know all of the details. And they
are confusing. I've written compilers in the past, and worked
with language standards for something like 20 years, and I still
have to go very, very slowly when attacking this in C++. (And
if you think that this is confusing, wait until you attack
function overload resolution, or name binding in templates.)
I indeed like to have a completely clear picture, though I see it's
impossible for me at the moment. I just hope to be more confident
when I write programs if I know which variables are visible at which
place and whether I'm referring to a variable that I intend to.

Thanks a lot!
Jess

Jun 5 '07 #13
On Jun 5, 7:33 am, Jess <w...@hotmail.c omwrote:
On Jun 4, 3:19 am, James Kanze <james.ka...@gm ail.comwrote:
On Jun 2, 4:04 pm, Jess <w...@hotmail.c omwrote:
[...]
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).
That's correct so far.
Therefore, I think line 3 is saying declare the "i" at
line 2 as external.
That would be logical, and it would be logical (IMHO) for the
above to be an error, since there are conflicting linkage
specifications. According to the standard, however, the "i" in
line 2 has no binding, so no other declaration can refer to it.
Thus, since line 3 can't refer to it, and line 1. isn't visible
at this point, line 3 declares still another i.
Thanks again. My email yesterday seemed to be deleted by google...
It's not an email, but a posting, and I also have the impression
that Google looses a few.
I'm still wondering why "i" at line2 is visible at line3, but there's
no binding for the "i" at line 2.
The "i" is visible because those are the rules of visibility in
C++ (and in most other scoped languages, I think). And the "i"
doesn't have linkage because that is also a rule of the
language.

Both of the rules, taken in isolation, make very good sense.
The problem is the interaction---since the "i" in 2 is visible,
I would normally expect that the declaration in 3 refers to it,
that it attempts to change the linkage, which isn't possible,
and so should be an error. But the standard says otherwise.

IMHO, it's not a real problem. There's never any reason to
declare an extern at local scope anyway---externs should always
be declared in header files, at namespace scope.
No binding means no linkage, is this correct?
No linkage is what I meant. No binding is a bit of sloppiness
on my part. (Binding is different than linkage, and isn't
relevant here.)
If so, is it completely useless to declare "i" at line 2? If
I have another line after line 2, but before the "{" above
line 3
static int i = 1 ; // 1.
void g()
{
std::cout << i ; // Outputs 1
int i = 2 ; // 2. Hides the static 1.
std::cout << i ; // Outputs 2
{
std::cout << i ; // Outputs 2
extern int i ; // 3. (Initialized to 3 elsewhere.
std::cout << i ; // Outputs 3
}
std::cout << i ; // Outputs 2
}

Although never for an extern, on very rare occasions, I've
introduced extra {} just to limit scope. In C++, this usually
occurs in order to ensure that the destructor is called at the
correct time, e.g.:

void
f()
{
// do something non critical...
{
scoped_lock l( someMutex ) ;
// locked region...
}
// unlocked here...
}
cout << i << endl;
then I think "i" at line 2 gets printed. Does it mean the "{" above
line 3 makes "i" at line 2 have no binding?
No. A variable declared at block scope (in a {...} in a
function) has no linkage by default; declaring it extern gives
it external linkage, unless there is a previous declaration
which has linkage and is visible.

The rules here are rather arbitrary, and I suspect that it's
another case of the committee just deciding that they had to
specify something, but it didn't matter much what. In good
code, you will not have any "extern" at block scope, so it
doesn't matter. But if you're writing a compiler, you have to
know what to do about it; a compiler has to work in a defined
manner even if fed "bad" code.
Whether you or I think that this is a good idea, or the way it
should be, is irrelevant. The above example is taken directly
from the standard.
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... :(
Well, you seemed to want to know all of the details. And they
are confusing. I've written compilers in the past, and worked
with language standards for something like 20 years, and I still
have to go very, very slowly when attacking this in C++. (And
if you think that this is confusing, wait until you attack
function overload resolution, or name binding in templates.)
I indeed like to have a completely clear picture, though I see it's
impossible for me at the moment. I just hope to be more confident
when I write programs if I know which variables are visible at which
place and whether I'm referring to a variable that I intend to.
I understand totally, but be aware that even with over 15 years
experience in C++, there are aspects which remain hazy to me.
That doesn't necessarily stop me from writing correct code. In
this case, for example, the complication only involves cases
where you declare a variable extern at block scope. Don't do
that, and there's no problem. Avoid the same names for
different objects, and you don't have to worry about whether the
name refers to a file local static, or to a global. (I'm not
saying that the rules are intuitive, but they're generally clear
enough that one can learn them.)

--
James Kanze (GABI Software) email:ja******* **@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Jun 5 '07 #14
On Jun 5, 5:49 pm, James Kanze <james.ka...@gm ail.comwrote:
On Jun 5, 7:33 am, Jess <w...@hotmail.c omwrote:
On Jun 4, 3:19 am, James Kanze <james.ka...@gm ail.comwrote:
On Jun 2, 4:04 pm, Jess <w...@hotmail.c omwrote:
[...]
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).
That's correct so far.
Therefore, I think line 3 is saying declare the "i" at
line 2 as external.
That would be logical, and it would be logical (IMHO) for the
above to be an error, since there are conflicting linkage
specifications. According to the standard, however, the "i" in
line 2 has no binding, so no other declaration can refer to it.
Thus, since line 3 can't refer to it, and line 1. isn't visible
at this point, line 3 declares still another i.
Thanks again. My email yesterday seemed to be deleted by google...

It's not an email, but a posting, and I also have the impression
that Google looses a few.
I'm still wondering why "i" at line2 is visible at line3, but there's
no binding for the "i" at line 2.

The "i" is visible because those are the rules of visibility in
C++ (and in most other scoped languages, I think). And the "i"
doesn't have linkage because that is also a rule of the
language.

Both of the rules, taken in isolation, make very good sense.
The problem is the interaction---since the "i" in 2 is visible,
I would normally expect that the declaration in 3 refers to it,
that it attempts to change the linkage, which isn't possible,
and so should be an error. But the standard says otherwise.

IMHO, it's not a real problem. There's never any reason to
declare an extern at local scope anyway---externs should always
be declared in header files, at namespace scope.
No binding means no linkage, is this correct?

No linkage is what I meant. No binding is a bit of sloppiness
on my part. (Binding is different than linkage, and isn't
relevant here.)
If so, is it completely useless to declare "i" at line 2? If
I have another line after line 2, but before the "{" above
line 3

static int i = 1 ; // 1.
void g()
{
std::cout << i ; // Outputs 1
int i = 2 ; // 2. Hides the static 1.
std::cout << i ; // Outputs 2
{
std::cout << i ; // Outputs 2
extern int i ; // 3. (Initialized to 3 elsewhere.
std::cout << i ; // Outputs 3
}
std::cout << i ; // Outputs 2
}

Although never for an extern, on very rare occasions, I've
introduced extra {} just to limit scope. In C++, this usually
occurs in order to ensure that the destructor is called at the
correct time, e.g.:

void
f()
{
// do something non critical...
{
scoped_lock l( someMutex ) ;
// locked region...
}
// unlocked here...
}
cout << i << endl;
then I think "i" at line 2 gets printed. Does it mean the "{" above
line 3 makes "i" at line 2 have no binding?

No. A variable declared at block scope (in a {...} in a
function) has no linkage by default; declaring it extern gives
it external linkage, unless there is a previous declaration
which has linkage and is visible.

The rules here are rather arbitrary, and I suspect that it's
another case of the committee just deciding that they had to
specify something, but it didn't matter much what. In good
code, you will not have any "extern" at block scope, so it
doesn't matter. But if you're writing a compiler, you have to
know what to do about it; a compiler has to work in a defined
manner even if fed "bad" code.
Whether you or I think that this is a good idea, or the way it
should be, is irrelevant. The above example is taken directly
from the standard.
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... :(
Well, you seemed to want to know all of the details. And they
are confusing. I've written compilers in the past, and worked
with language standards for something like 20 years, and I still
have to go very, very slowly when attacking this in C++. (And
if you think that this is confusing, wait until you attack
function overload resolution, or name binding in templates.)
I indeed like to have a completely clear picture, though I see it's
impossible for me at the moment. I just hope to be more confident
when I write programs if I know which variables are visible at which
place and whether I'm referring to a variable that I intend to.

I understand totally, but be aware that even with over 15 years
experience in C++, there are aspects which remain hazy to me.
That doesn't necessarily stop me from writing correct code. In
this case, for example, the complication only involves cases
where you declare a variable extern at block scope. Don't do
that, and there's no problem. Avoid the same names for
different objects, and you don't have to worry about whether the
name refers to a file local static, or to a global. (I'm not
saying that the rules are intuitive, but they're generally clear
enough that one can learn them.)

--
James Kanze (GABI Software) email:james.ka. ..@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Thanks a lot for clarifying the matter, I think I understand it, at
least for now. :)
Jess

Jun 6 '07 #15

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

29
4405
by: Alexander Mahr | last post by:
Dear Newsgroup, I'm somehow confused with the usage of the static keyword. I can see two function of the keyword static in conjunction with a data member of a class. 1. The data member reffers in all objects of this class to the same data Or in other word by using the static keyword all objects of one class can share data. (This is what I want)
1
1472
by: Harald Deischinger | last post by:
I am using a source file with the following style (I know it is not very beautiful but it is working): SRC1.cpp: static void vFoo() { // bla bla bla } static int iInit1(name, fun) { // access some global variables to register fun as name.
4
2324
by: jr | last post by:
I am working in VC++ so this may be microsoft specific though I don't think so. Excuse me if it is. Assuming it isn't, can someone generally explain the purpose of having both - is it purely a deployment/distribution thing. I notice that the static library generates obj files and a Lib file. Could someone kindly explain how they relate to one another. Thanks very much
12
13467
by: cppaddict | last post by:
Hi, I know that it is illegal in C++ to have a static pure virtual method, but it seems something like this would be useful when the following 2 conditions hold: 1. You know that every one of your Derived classes will need to implement some method, but implement it differently, and that the base class cannot implement it. This is where pure virtual comes in.
3
1385
by: ruud.bos | last post by:
Hi list, As a C++ newbie, I have a question about static member functions. Suppose I have the following class definition: class MyClass { public: static void MyFunc(); };
2
9086
by: Lu | last post by:
Hello, I am wondering how to protect a global variable in a header file from external access. So I googled and found: "The keyword 'static' has two different uses, depending on whether it is applied to an external variable or function or to an automatic variable. When applied to an external variable (global) variable the scope of that variable to the file in which it is declared. This is useful to hide buffers and variables that are used...
9
2310
by: Neil Kiser | last post by:
I'm trying to understand what defining a class as 'static' does for me. Here's an example, because maybe I am thinking about this all wrong: My app will allows the user to control the fonts that the app uses. So I will need to change the fonts depending on what settings the user has entered. However, it seems kind of wasteful to me to go to teh registry, fetch the font information and create new font objects for every form that I am...
3
5858
by: Steve Folly | last post by:
Hi, I had a problem in my code recently which turned out to be the 'the "static initialization order fiasco"' problem (<http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.12>) The FAQ section describes a solution using methods returning references to static objects. But consider:
2
11713
by: chenxinleo | last post by:
Hi, When i use some standard library functions and fields,which return char* type(like ctime in time.h, optarg in getopt.h)and do not have to be freed after calling,i always worry about memory leaking(thoug i konw i just donot have to).Then i look inside in time.h file(mingw) ,and i found notes say"These functions write to and return pointers to static buffers that may be overwritten by other function calls".So how is the"static buffers"...
0
10069
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
9904
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
9884
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
8736
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7285
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6556
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5168
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
2
3395
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2697
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.