|
|
 |
 |
 |
 |
"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
> 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?
somefile.hxx: ------------ struct A { } ; extern A object_in_global_namespace ; namespace foo { extern A object_in_foo_namespace ; }
struct X { static A object_inside_class ; } ;
void function_with_local_static() ; somefile.cxx: ------------ A object_in_global_namespace ; namespace foo { A object_in_foo_namespace ; }
A X::object_inside_class ; void function_with_local_static() { static A local_static ; // ... }
namespace { A internal_linkage_object ; // ("file scope" object) } > 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?
"extern A a" is a *declaration* of a global object. It says, "when you link, expect to find the definition somewhere." The defintion, "A a", is placed inside a source file (not a header). You are placing way too much emphasis on the literal meaning of the word "static". It has some historical baggage which I will not dive into. In modern C++, the only use of "static" should be inside class definitions and inside functions. In the former case, it is used to differentiate between per-instance and per-class; in the latter case, it is used to differentiate between automatic storage and persistent (static) storage. > 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?
If you put "static" in front of a regular function, that's deprecated usage. It originally meant internal linkage, but that's done with anonymous namespaces now. Don't do that. Again, don't read too much into the literal meaning of the word. > 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?
The former. "extern A a" is a declaration. It does not declare that the object is constructed with the default constructor. Where it is defined, it may be constructed with any constructor, e.g., "A a(44)".
On May 30, 9:38 am, jeffjohnson_al@yahoo.com wrote: > You are placing way too much emphasis on the literal meaning of the > word "static". [...] In the former case, it is used to differentiate > between per-instance and per-class [...]
Argh, I had my mind in ruby mode when I wrote "per-class" (classes in ruby are singleton objects which hold per-class data). Of course this is not the case in C++; the storage of static class members is the regular static storage.
Hi jeffjohnson_al @yahoo.com wrote: > namespace { > A internal_linkage_object ; // ("file scope" object) > } [...] > If you put "static" in front of a regular function, that's deprecated > usage. It originally meant internal linkage, but that's done with > anonymous namespaces now. Don't do that. Again, don't read too much > into the literal meaning of the word. That's incorrect. Names declared in unnamed namespaces still have external linkage. However, there is no (portable) way to access the named object from within another translation unit. Markus
On May 31, 5:38 am, Markus Moll <m@rbg.informatik.tu-darmstadt.de> wrote:
> Hi > jeffjohnson_al@yahoo.com wrote: > > namespace { > > A internal_linkage_object ; // ("file scope" object) > > } > [...] > > If you put "static" in front of a regular function, that's deprecated > > usage. It originally meant internal linkage, but that's done with > > anonymous namespaces now. Don't do that. Again, don't read too much > > into the literal meaning of the word. > That's incorrect. Names declared in unnamed namespaces still have external > linkage. However, there is no (portable) way to access the named object > from within another translation unit.
If it still has external linkage, then why is it not accessible from another translation unit? I thought "external linkage" means it's visible outside its own translation unit... Thanks, Jess
On May 31, 8:41 am, Jess <w@hotmail.com> wrote:
> On May 31, 5:38 am, Markus Moll <m @rbg.informatik.tu-darmstadt.de> > wrote: > > jeffjohnson_al @yahoo.com wrote: > > > namespace { > > > A internal_linkage_object ; // ("file scope" object) > > > } > > [...] > > > If you put "static" in front of a regular function, that's deprecated > > > usage. It originally meant internal linkage, but that's done with > > > anonymous namespaces now. Don't do that. Again, don't read too much > > > into the literal meaning of the word. > > That's incorrect. Names declared in unnamed namespaces still have external > > linkage. However, there is no (portable) way to access the named object > > from within another translation unit. > If it still has external linkage, then why is it not accessible from > another translation unit? It is, in some very special cases. (It can be used in the instantiation of an exported template, for example.) Generally, however, there is no way to name it. > I thought "external linkage" means it's > visible outside its own translation unit...
It is visible, at least conceptually. But since you have no way to refer to it, it's "visibility" is rather accademic. And of course, visibility isn't really the word you want. External linkage means that the same (fully qualified) name in different translation units refers to the same, single object. When you write: namespace { int x ; } this defines an object with type int and the name <secret>::x. Any references to <secret>::x, from any translation unit in the entire program, refer to the same object. The compiler, however, generates a different <secret> for each translation unit, and generates it in a way that you cannot even accidentally hit on it. So about the only way you can refer to it in another translation unit is when instantiating an exported template. -- James Kanze (GABI Software) email:james.ka@gmail.com Conseils en informatique oriente objet/ Beratung in objektorientierter Datenverarbeitung 9 place Smard, 78210 St.-Cyr-l'cole, France, +33 (0)1 30 23 00 34
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.) -- 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.) With regards to your exact question, I'm not too sure what you're asking. A "global object" is normally an object declared and defined in the global namespace without the static keyword, i.e. an object in namespace scope and with external linkage. By definition, it can't be declared static (but it always has static lifetime), because if it were, it wouldn't be a global object. And there is no "file scope" in C++; if by "file scope" you mean outside of any namespace, class or function, then that is "global scope", or the "global namespace". Note too that the use of static at namespace scope is deprecated. It is generally preferred to use an anonymous namespace. (On the other hand, the names of variables declared "const" have internal linkage, just as if they were declared static, unless they are explicitly declared "extern".) As to when you would use them: the classical singleton idiom is a good example of static used at class scope: class Singleton { public: static Singleton& instance() ; // ... private: static Singleton* ourInstance ; } ; The function instance() can (and will be) called without an instance of the object, and the variable ourInstance will have static lifetime, existing before the first instance is created, and after the last one is destructed. At local scope, one might use a static variable to keep track of recursion: void* operator new( size_t n ) { static bool recursing = false ; void* result = NULL ; if ( recursing ) { result = getMemory( n ) ; } else { recursing = true ; std::cerr << "allocating " << n << " bytes at " ; result = getMemory( n ) ; std::cerr << result << std::endl ; recursing = false ; } return result ; } This is necessary here, since outputting to std::cerr could very easily end up calling operator new. -- James Kanze (GABI Software) email:james.ka@gmail.com Conseils en informatique oriente objet/ Beratung in objektorientierter Datenverarbeitung 9 place Smard, 78210 St.-Cyr-l'cole, France, +33 (0)1 30 23 00 34
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? I think "internal linkage" means it's only accessible within this current translation unit, is this also right? Furthermore, I tried one example as follows: //test.h class A{ public: int x; A():x(10){} };
namespace foo{ static extern A b; }
//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? > -- 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? How can a function be declared within such local scope? By the way, I think "no linkage" means it is only accessible within that local scope where it's defined, is this correct? > With regards to your exact question, I'm not too sure what > you're asking. A "global object" is normally an object declared > and defined in the global namespace without the static keyword, > i.e. an object in namespace scope and with external linkage. By > definition, it can't be declared static (but it always has > static lifetime), because if it were, it wouldn't be a global > object. And there is no "file scope" in C++; if by "file scope" > you mean outside of any namespace, class or function, then that > is "global scope", or the "global namespace".
My interpretation about "global" namespace is that I don't use any "namespace" to surround my object/function, please correct me if I'm wrong. Then, why did you say a global object is "an object in namespace scope and with external linkage"? In other words, do I still need to use "namespace" to wrap it up? I got the terms "global objects" and "objects at file scope" from the book Effective C++. My understanding about them is that a global object has external linkage (accessible from other translation units), and a file-scope-object is only accessible within that translation unit (but not limited to any local scope within that translation unit). Is this not the intended meaning of the author? > Note too that the use of static at namespace scope is > deprecated. It is generally preferred to use an anonymous > namespace. (On the other hand, the names of variables declared > "const" have internal linkage, just as if they were declared > static, unless they are explicitly declared "extern".)
I tried another example, which also failed to compile. //test.h namespace foo{ static extern const int x; };
//test.cpp #include "test.h" namespace foo{ static const int x = 10; }
#include "test.h" #include<iostream> using namespace std; int main(){ cout << foo::x << endl; return 0; }
However, after I removed the static keyword, it compiled and worked. Does a const inside a namespace have external or internal linkage? Moreover, it just seems to me that I can never declare "static" within a namespace. Moreover, do all objects that have external linkage have static lifetime? not a single exception? Finally, I noticed that sometimes when I declare a static object, I need "static" keyword, but when I define it, I don't need "static". Does this depend on the context or, do we not need "static" in general when we define it? Thanks very much indeed, Jess
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? I think "internal linkage" means it's only accessible within this current translation unit, is this also right? Furthermore, I tried one example as follows: //test.h class A{ public: int x; A():x(10){} };
namespace foo{ static extern A b; }
//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? > -- 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? How can a function be declared within such local scope? By the way, I think "no linkage" means it is only accessible within that local scope where it's defined, is this correct? > With regards to your exact question, I'm not too sure what > you're asking. A "global object" is normally an object declared > and defined in the global namespace without the static keyword, > i.e. an object in namespace scope and with external linkage. By > definition, it can't be declared static (but it always has > static lifetime), because if it were, it wouldn't be a global > object. And there is no "file scope" in C++; if by "file scope" > you mean outside of any namespace, class or function, then that > is "global scope", or the "global namespace".
My interpretation about "global" namespace is that I don't use any "namespace" to surround my object/function, please correct me if I'm wrong. Then, why did you say a global object is "an object in namespace scope and with external linkage"? In other words, do I still need to use "namespace" to wrap it up? I got the terms "global objects" and "objects at file scope" from the book Effective C++. My understanding about them is that a global object has external linkage (accessible from other translation units), and a file-scope-object is only accessible within that translation unit (but not limited to any local scope within that translation unit). Is this not the intended meaning of the author? > Note too that the use of static at namespace scope is > deprecated. It is generally preferred to use an anonymous > namespace. (On the other hand, the names of variables declared > "const" have internal linkage, just as if they were declared > static, unless they are explicitly declared "extern".)
I tried another example, which also failed to compile. //test.h namespace foo{ static extern const int x; };
//test.cpp #include "test.h" namespace foo{ static const int x = 10; }
#include "test.h" #include<iostream> using namespace std; int main(){ cout << foo::x << endl; return 0; }
However, after I removed the static keyword, it compiled and worked. Does a const inside a namespace have external or internal linkage? Moreover, it just seems to me that I can never declare "static" within a namespace. Moreover, do all objects that have external linkage have static lifetime? not a single exception? Finally, I noticed that sometimes when I declare a static object, I need "static" keyword, but when I define it, I don't need "static". Does this depend on the context or, do we not need "static" in general when we define it? Thanks very much indeed, Jess
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.) 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>. 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). (And if you aren't thoroughly confused yet, you should be.) > > With regards to your exact question, I'm not too sure what > > you're asking. A "global object" is normally an object declared > > and defined in the global namespace without the static keyword, > > i.e. an object in namespace scope and with external linkage. By > > definition, it can't be declared static (but it always has > > static lifetime), because if it were, it wouldn't be a global > > object. And there is no "file scope" in C++; if by "file scope" > > you mean outside of any namespace, class or function, then that > > is "global scope", or the "global namespace". > My interpretation about "global" namespace is that I don't use any > "namespace" to surround my object/function, please correct me if I'm > wrong.
Correct. The concept is that the entire translation unit is encapsulated in an outer namespace, which is called the global namespace. > Then, why did you say a global object is "an object in > namespace scope and with external linkage"? In other words, do I still > need to use "namespace" to wrap it up?
No. Namespace scope includes objects defined in this imaginary namespace which encapsulates the entire translation unit. (On the other hand, it doesn't include built in types, like int. Which occasionally causes problems when code is counting on ADL.)
> I got the terms "global objects" and "objects
... read more »
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-
... read more »
On Jun 2, 4:04 pm, Jess <w@hotmail.com> wrote: [...] > 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?
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_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?
Because the standard says that if something can be interpreted as a declaration, it is. Both of the sub-expressions "std::istream_iterator< int >( file )" and "std::istream_iterator< 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::vector< int >", and B for "std::istream_iterator< 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::vector< 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: james.ka@gmail.com Conseils en informatique oriente objet/ Beratung in objektorientierter Datenverarbeitung 9 place Smard, 78210 St.-Cyr-l'cole, France, +33 (0)1 30 23 00 34
On Jun 4, 3:19 am, James Kanze <james.ka@gmail.com> wrote:
> On Jun 2, 4:04 pm, Jess <w @hotmail.com> wrote: > [...] > > 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? > 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_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? > Because the standard says that if something can be interpreted > as a declaration, it is. Both of the sub-expressions > "std::istream_iterator< int >( file )" and > "std::istream_iterator< 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::vector< int >", and B for "std::istream_iterator< 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::vector< 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
On Jun 5, 7:33 am, Jess <w@hotmail.com> wrote:
> On Jun 4, 3:19 am, James Kanze <james.ka @gmail.com> wrote: > > On Jun 2, 4:04 pm, Jess <w @hotmail.com> wrote: > > [...] > > > > 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 oriente objet/ Beratung in objektorientierter Datenverarbeitung 9 place Smard, 78210 St.-Cyr-l'cole, France, +33 (0)1 30 23 00 34
On Jun 5, 5:49 pm, James Kanze <james.ka@gmail.com> wrote:
> On Jun 5, 7:33 am, Jess <w @hotmail.com> wrote: > > On Jun 4, 3:19 am, James Kanze <james.ka@gmail.com> wrote: > > > On Jun 2, 4:04 pm, Jess <w@hotmail.com> wrote: > > > [...] > > > > > 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 oriente objet/ > Beratung in objektorientierter Datenverarbeitung > 9 place Smard, 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
|
 |
 |
 |
 |
|