Home     |     .Net Programming    |     cSharp Home    |     Sql Server Home    |     Javascript / Client Side Development     |     Ajax Programming

Ruby on Rails Development     |     Perl Programming     |     C Programming Language     |     C++ Programming     |     IT Jobs

Python Programming Language     |     Laptop Suggestions?    |     TCL Scripting     |     Fortran Programming     |     Scheme Programming Language


 
 
Cervo Technologies
The Right Source to Outsource

MS Dynamics CRM 3.0

C++ Programming

"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:

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:

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:

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:

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:

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."

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

...

read more »

On Jun 1, 10:43 pm, James Kanze <james.ka@gmail.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?

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.

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.

    [...]

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

    [...]

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:

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?

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:

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.

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:

Thanks a lot for clarifying the matter, I think I understand it, at
least for now. :)
Jess
Add to del.icio.us | Digg this | Stumble it | Powered by Megasolutions Inc