initializing static class variables

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Neil Zanella

    initializing static class variables

    Hello,

    When an "std::map<i nt, int> foobar;" statement appears in a C++ program
    followed by a statement of the form "foobar[123];" where nothing has ever
    been inserted at position 123 into map foobar, the C++ standard states
    that a new element is created at position 123 and is initialized to
    zero. That is, in this case, the pair (123, 0) is inserted into the
    map.

    I am interested in knowing what the standard says should happen in the
    following case. Does the standard mandate that struct Foo's pointers be
    initialized to zero as well, upon reference to hello[110], or does this
    program lead to undefined behavior.

    Thank you for your feedback and explanations,

    Neil

    #include <iostream>
    #include <map>

    struct Foo {
    int *x;
    int *y;
    };

    typedef std::map<int, Foo> Hello;

    int main() {
    Hello hello;
    //initialize entiry structure, hence also its pointers, to zero
    //(I believe this is according to the ANSI/ISO C++ standard too)
    std::cout << hello[110].x << std::endl;
    //hence dereferencing zero memory address causes segfault
    //std::cout << *hello[110].x << std::endl;
    //hence same goes for assigning
    *hello[110].x = 112;
    }
  • Dave Townsend

    #2
    Re: initializing static class variables


    I believe the STL standard says an object will be constructed
    with the default constructor in this situation. Since you don't have
    one, the values of x and y will be undefined (garbage) when you
    insert a new key

    dave

    "Neil Zanella" <nzanella@cs.mu n.ca> wrote in message
    news:b68d2f19.0 407291628.14c1b ba4@posting.goo gle.com...[color=blue]
    > Hello,
    >
    > When an "std::map<i nt, int> foobar;" statement appears in a C++ program
    > followed by a statement of the form "foobar[123];" where nothing has ever
    > been inserted at position 123 into map foobar, the C++ standard states
    > that a new element is created at position 123 and is initialized to
    > zero. That is, in this case, the pair (123, 0) is inserted into the
    > map.
    >
    > I am interested in knowing what the standard says should happen in the
    > following case. Does the standard mandate that struct Foo's pointers be
    > initialized to zero as well, upon reference to hello[110], or does this
    > program lead to undefined behavior.
    >
    > Thank you for your feedback and explanations,
    >
    > Neil
    >
    > #include <iostream>
    > #include <map>
    >
    > struct Foo {
    > int *x;
    > int *y;
    > };
    >
    > typedef std::map<int, Foo> Hello;
    >
    > int main() {
    > Hello hello;
    > //initialize entiry structure, hence also its pointers, to zero
    > //(I believe this is according to the ANSI/ISO C++ standard too)
    > std::cout << hello[110].x << std::endl;
    > //hence dereferencing zero memory address causes segfault
    > //std::cout << *hello[110].x << std::endl;
    > //hence same goes for assigning
    > *hello[110].x = 112;
    > }[/color]


    Comment

    • John Harrison

      #3
      Re: initializing static class variables

      On Thu, 29 Jul 2004 18:07:27 -0700, Dave Townsend <datownsend@com cast.net>
      wrote:
      [color=blue]
      >
      > I believe the STL standard says an object will be constructed
      > with the default constructor in this situation. Since you don't have
      > one, the values of x and y will be undefined (garbage) when you
      > insert a new key
      >
      > dave
      >[/color]

      I don't believe that is correct, the standard says that hello[110] is
      equivalvent to

      (*((insert(make _pair(100,Foo() ))).first)).sec ond;

      he crucial bit is Foo() which is value initialisation not default
      initialisation. For value initialisation of Foo, x and y will be zero
      initialised.

      However I think value iniitalisation is a fairly new concept in the
      C++ standard and I wouldn't be surprised if a compiler got this wrong.

      Also I'm not completely certain of this, and I'm really just posting to
      put the alternative view. The releveant sections of the standard are 8.5,
      23.3.1.2, 5.2.3 for anyone who want's to check this out. Maybe one of the
      gurus could clear this up.

      Either way the safe thing to do is to add a default constructor to Foo.

      john
      [color=blue]
      > "Neil Zanella" <nzanella@cs.mu n.ca> wrote in message
      > news:b68d2f19.0 407291628.14c1b ba4@posting.goo gle.com...[color=green]
      >> Hello,
      >>
      >> When an "std::map<i nt, int> foobar;" statement appears in a C++ program
      >> followed by a statement of the form "foobar[123];" where nothing has
      >> ever
      >> been inserted at position 123 into map foobar, the C++ standard states
      >> that a new element is created at position 123 and is initialized to
      >> zero. That is, in this case, the pair (123, 0) is inserted into the
      >> map.
      >>
      >> I am interested in knowing what the standard says should happen in the
      >> following case. Does the standard mandate that struct Foo's pointers be
      >> initialized to zero as well, upon reference to hello[110], or does this
      >> program lead to undefined behavior.
      >>
      >> Thank you for your feedback and explanations,
      >>
      >> Neil
      >>
      >> #include <iostream>
      >> #include <map>
      >>
      >> struct Foo {
      >> int *x;
      >> int *y;
      >> };
      >>
      >> typedef std::map<int, Foo> Hello;
      >>
      >> int main() {
      >> Hello hello;
      >> //initialize entiry structure, hence also its pointers, to zero
      >> //(I believe this is according to the ANSI/ISO C++ standard too)
      >> std::cout << hello[110].x << std::endl;
      >> //hence dereferencing zero memory address causes segfault
      >> //std::cout << *hello[110].x << std::endl;
      >> //hence same goes for assigning
      >> *hello[110].x = 112;
      >> }[/color]
      >
      >[/color]

      Comment

      • Dave Townsend

        #4
        Re: initializing static class variables

        John,

        thanks for point out this subtlety. Can you post an example which
        demonstrates the difference, I've heard mention of these two types
        of initialization but never got on to what the difference was.

        thanks, dave

        "John Harrison" <john_andronicu s@hotmail.com> wrote in message
        news:opsbxp9wq7 212331@andronic us...[color=blue]
        > On Thu, 29 Jul 2004 18:07:27 -0700, Dave Townsend <datownsend@com cast.net>
        > wrote:
        >[color=green]
        > >
        > > I believe the STL standard says an object will be constructed
        > > with the default constructor in this situation. Since you don't have
        > > one, the values of x and y will be undefined (garbage) when you
        > > insert a new key
        > >
        > > dave
        > >[/color]
        >
        > I don't believe that is correct, the standard says that hello[110] is
        > equivalvent to
        >
        > (*((insert(make _pair(100,Foo() ))).first)).sec ond;
        >
        > he crucial bit is Foo() which is value initialisation not default
        > initialisation. For value initialisation of Foo, x and y will be zero
        > initialised.
        >
        > However I think value iniitalisation is a fairly new concept in the
        > C++ standard and I wouldn't be surprised if a compiler got this wrong.
        >
        > Also I'm not completely certain of this, and I'm really just posting to
        > put the alternative view. The releveant sections of the standard are 8.5,
        > 23.3.1.2, 5.2.3 for anyone who want's to check this out. Maybe one of the
        > gurus could clear this up.
        >
        > Either way the safe thing to do is to add a default constructor to Foo.
        >
        > john
        >[color=green]
        > > "Neil Zanella" <nzanella@cs.mu n.ca> wrote in message
        > > news:b68d2f19.0 407291628.14c1b ba4@posting.goo gle.com...[color=darkred]
        > >> Hello,
        > >>
        > >> When an "std::map<i nt, int> foobar;" statement appears in a C++ program
        > >> followed by a statement of the form "foobar[123];" where nothing has
        > >> ever
        > >> been inserted at position 123 into map foobar, the C++ standard states
        > >> that a new element is created at position 123 and is initialized to
        > >> zero. That is, in this case, the pair (123, 0) is inserted into the
        > >> map.
        > >>
        > >> I am interested in knowing what the standard says should happen in the
        > >> following case. Does the standard mandate that struct Foo's pointers be
        > >> initialized to zero as well, upon reference to hello[110], or does this
        > >> program lead to undefined behavior.
        > >>
        > >> Thank you for your feedback and explanations,
        > >>
        > >> Neil
        > >>
        > >> #include <iostream>
        > >> #include <map>
        > >>
        > >> struct Foo {
        > >> int *x;
        > >> int *y;
        > >> };
        > >>
        > >> typedef std::map<int, Foo> Hello;
        > >>
        > >> int main() {
        > >> Hello hello;
        > >> //initialize entiry structure, hence also its pointers, to zero
        > >> //(I believe this is according to the ANSI/ISO C++ standard too)
        > >> std::cout << hello[110].x << std::endl;
        > >> //hence dereferencing zero memory address causes segfault
        > >> //std::cout << *hello[110].x << std::endl;
        > >> //hence same goes for assigning
        > >> *hello[110].x = 112;
        > >> }[/color]
        > >
        > >[/color]
        >[/color]


        Comment

        • John Harrison

          #5
          Re: initializing static class variables

          On Thu, 29 Jul 2004 22:26:07 -0700, Dave Townsend <datownsend@com cast.net>
          wrote:
          [color=blue]
          > John,
          >
          > thanks for point out this subtlety. Can you post an example which
          > demonstrates the difference, I've heard mention of these two types
          > of initialization but never got on to what the difference was.
          >
          > thanks, dave
          >[/color]

          Well I don't want to sound more certain than I am, but here goes.

          8.5 para 7 of the standard says

          An object whose initialiser is an empty set of parentheses i.e., (), shall
          be value-initialized.

          So I reckon in this code

          class Bar
          {
          Bar() : foo() {}
          Bar(int) {}
          private:
          Foo foo;
          };

          the first constructor value initialises foo, and the second default
          initialises it.

          Ditto

          Foo* foo = new Foo(); // value initialisation
          Foo* foo2 = new Foo; // default initialisation

          john

          Comment

          • Neil Zanella

            #6
            Re: initializing static class variables

            Interesting, you must all be referring to the new C++ standard
            available
            from ANSI (at USD 18.0 for the electronic version). It also seems like
            the
            older 1998 standard has been discontinued.



            So what is the difference between default initialization
            and value initialization? Is this something introduced
            in the 2003 standard?

            Thanks,

            Neil

            class Foo {
            public:
            Foo() { }
            };

            class Bar {
            public:
            Bar(): foo() { }
            Bar(int) { }
            private:
            Foo foo;
            };

            int main() {
            Foo *foo = new Foo();
            Foo *foo2 = new Foo;
            Foo foo3;
            Foo foo4();
            }

            Comment

            • John Harrison

              #7
              Re: initializing static class variables

              On 31 Jul 2004 11:44:01 -0700, Neil Zanella <nzanella@cs.mu n.ca> wrote:
              [color=blue]
              > Interesting, you must all be referring to the new C++ standard
              > available
              > from ANSI (at USD 18.0 for the electronic version). It also seems like
              > the
              > older 1998 standard has been discontinued.
              >
              > http://webstore.ansi.org/ansidocstor...C+14882%2D2003
              >
              > So what is the difference between default initialization
              > and value initialization? Is this something introduced
              > in the 2003 standard?
              >
              > Thanks,
              >
              > Neil
              >[/color]

              I believe it was introduced in 2003 standard but I can't be sure since I
              don't have the 1998 standard available.

              I guess the difference is best illustrated with an example

              struct Foo
              {
              int x;
              };

              The standard says (8.5 para 5) that if Foo is default initialised then its
              default constructor is called. This is obviously an implicit default
              constructor and 12.1 para 7 and 12.6.2 para 4 together say that x is not
              initialised in this case (i.e. it has an undefined value).

              Hoever 8.5 para 5 says that if Foo is value initialised then because Foo
              does not have a user-declared constructor each of its members is value
              initialised. And when a scalar type is value initalsed it is in fact zero
              initialised.

              So

              #include <iostream>
              using namespace std;

              struct Foo
              {
              int x;
              };

              int main()
              {
              int* a = new int;
              cout << *a << '\n';
              int* b = new int();
              cout << *b << '\n';
              Foo* c = new Foo;
              cout << c->x << '\n';
              Foo* d = new Foo();
              cout << d->x << '\n';
              }

              Output with MSVC++ 7.1

              -842150451
              0
              -842150451
              0

              But I'm still learning this stuff myself, so watch out I could easily be
              wrong.

              john

              Comment

              • Mark

                #8
                Re: initializing static class variables

                On Sat, 31 Jul 2004 20:12:43 +0100, "John Harrison"
                <john_andronicu s@hotmail.com> wrote:

                [color=blue]
                >I believe it was introduced in 2003 standard but I can't be sure since I
                >don't have the 1998 standard available.
                >
                >I guess the difference is best illustrated with an example
                >
                >struct Foo
                >{
                > int x;
                >};
                >
                >The standard says (8.5 para 5) that if Foo is default initialised then its
                >default constructor is called. This is obviously an implicit default
                >constructor and 12.1 para 7 and 12.6.2 para 4 together say that x is not
                >initialised in this case (i.e. it has an undefined value).
                >
                >Hoever 8.5 para 5 says that if Foo is value initialised then because Foo
                >does not have a user-declared constructor each of its members is value
                >initialised. And when a scalar type is value initalsed it is in fact zero
                >initialised.
                >[/color]
                [....][color=blue]
                >
                >But I'm still learning this stuff myself, so watch out I could easily be
                >wrong.
                >
                >john[/color]

                Default initilization when viewed from the 1998 and 03 version of the
                standard seem contradictory.

                The 1998 standard for C++ (ISO/IEC 14882-1998) says:

                "An object whose initializer is an empty set of parentheses, i.e., (),
                shall be default-initialized."

                A little before that, it says:

                "To default-initialize an object of type T means:
                ** if T is a non-POD class type (clause 9), the default constructor
                for T is called (and the initialization is ill-formed if T has no
                accessible default constructor);
                ** if T is an array type, each element is default-initialized;
                ** otherwise, the storage for the object is zero-initialized."

                (Section 8.5, Initializers)

                So given

                struct data_t
                {
                int Idx;
                int Jdx;
                int Kdx;
                } data;

                data_t type is a POD class type (plain old data), so with empty
                parentheses, it should be zero-initialized.

                data_t() is not exactly a constructor call. It denotes a temporary
                object of type data_t, constructed with default initialization.

                So data(data_t()) initializes the object named "data" with a
                temporary, default-initialized object of its type, and for this type
                default initialization is zero-initialization.

                Note that some compilers may not do this right. In any event, it
                seems to me the 03 version of the standard refers to this as value
                initilization.

                Mark
                --
                [ C++ FAQ: http://www.parashift.com/c++-faq-lite/ ]

                Comment

                • John Harrison

                  #9
                  Re: initializing static class variables

                  On Sat, 31 Jul 2004 23:28:10 -0400, Mark <mark_netNews@h otmail.com> wrote:
                  [color=blue]
                  > On Sat, 31 Jul 2004 20:12:43 +0100, "John Harrison"
                  > <john_andronicu s@hotmail.com> wrote:
                  >
                  >[color=green]
                  >> I believe it was introduced in 2003 standard but I can't be sure since I
                  >> don't have the 1998 standard available.
                  >>
                  >> I guess the difference is best illustrated with an example
                  >>
                  >> struct Foo
                  >> {
                  >> int x;
                  >> };
                  >>
                  >> The standard says (8.5 para 5) that if Foo is default initialised then
                  >> its
                  >> default constructor is called. This is obviously an implicit default
                  >> constructor and 12.1 para 7 and 12.6.2 para 4 together say that x is not
                  >> initialised in this case (i.e. it has an undefined value).
                  >>
                  >> Hoever 8.5 para 5 says that if Foo is value initialised then because Foo
                  >> does not have a user-declared constructor each of its members is value
                  >> initialised. And when a scalar type is value initalsed it is in fact
                  >> zero
                  >> initialised.
                  >>[/color]
                  > [....][color=green]
                  >>
                  >> But I'm still learning this stuff myself, so watch out I could easily be
                  >> wrong.
                  >>
                  >> john[/color]
                  >
                  > Default initilization when viewed from the 1998 and 03 version of the
                  > standard seem contradictory.
                  >
                  > The 1998 standard for C++ (ISO/IEC 14882-1998) says:
                  >
                  > "An object whose initializer is an empty set of parentheses, i.e., (),
                  > shall be default-initialized."[/color]

                  That's directly contradicted by the 2003 standard which says value
                  initialised.
                  [color=blue]
                  >
                  > A little before that, it says:
                  >
                  > "To default-initialize an object of type T means:
                  > ** if T is a non-POD class type (clause 9), the default constructor
                  > for T is called (and the initialization is ill-formed if T has no
                  > accessible default constructor);
                  > ** if T is an array type, each element is default-initialized;
                  > ** otherwise, the storage for the object is zero-initialized."
                  >
                  > (Section 8.5, Initializers)
                  >
                  > So given
                  >
                  > struct data_t
                  > {
                  > int Idx;
                  > int Jdx;
                  > int Kdx;
                  > } data;
                  >
                  > data_t type is a POD class type (plain old data), so with empty
                  > parentheses, it should be zero-initialized.[/color]

                  Assuming you are talking about the 1998 standard I don't think so. Look up
                  the definition of compiler generated default constructor. I think you will
                  see that it says Idx, Jdx and Kdx remain uninitialised not zero
                  initialised.
                  [color=blue]
                  >
                  > data_t() is not exactly a constructor call. It denotes a temporary
                  > object of type data_t, constructed with default initialization.
                  >
                  > So data(data_t()) initializes the object named "data" with a
                  > temporary, default-initialized object of its type, and for this type
                  > default initialization is zero-initialization.
                  >
                  > Note that some compilers may not do this right. In any event, it
                  > seems to me the 03 version of the standard refers to this as value
                  > initilization.[/color]

                  And that's the crucial difference, because value initialisation does not
                  use the compiler generated default constructor.

                  john

                  Comment

                  • Mark

                    #10
                    Re: initializing static class variables

                    On Sun, 01 Aug 2004 07:36:46 +0100, "John Harrison"
                    <john_andronicu s@hotmail.com> wrote:

                    [...]
                    [color=blue][color=green]
                    >> (Section 8.5, Initializers)
                    >>
                    >> So given
                    >>
                    >> struct data_t
                    >> {
                    >> int Idx;
                    >> int Jdx;
                    >> int Kdx;
                    >> } data;
                    >>
                    >> data_t type is a POD class type (plain old data), so with empty
                    >> parentheses, it should be zero-initialized.[/color]
                    >
                    >Assuming you are talking about the 1998 standard I don't think so. Look up
                    >the definition of compiler generated default constructor. I think you will
                    >see that it says Idx, Jdx and Kdx remain uninitialised not zero
                    >initialised.
                    >[/color]
                    If I run test program below through Visual Studio 7.1. Then run said
                    program through Borland C++ Builder 4. The end result. Builder 4 did
                    zero initialize the struct while Visual Studio didn't.


                    # include<cstdio>

                    class test
                    {
                    private:
                    struct data_t
                    {
                    int mem1;
                    double mem2;
                    char mem3;
                    double mem4[50];
                    } data;
                    public:
                    test()
                    :data(data_t()) //zero initialises data
                    {
                    printf( "mem1 = %d\n", data.mem1 );
                    printf( "mem2 = %f\n", data.mem2 );
                    }
                    };

                    int main(int argc, char* argv[])
                    {
                    test mytest;
                    }

                    Mark
                    --
                    [ C++ FAQ: http://www.parashift.com/c++-faq-lite/ ]

                    Comment

                    • John Harrison

                      #11
                      Re: initializing static class variables

                      On Sun, 01 Aug 2004 22:25:28 -0400, Mark <mark_netNews@h otmail.com> wrote:
                      [color=blue]
                      > On Sun, 01 Aug 2004 07:36:46 +0100, "John Harrison"
                      > <john_andronicu s@hotmail.com> wrote:
                      >
                      > [...]
                      >[color=green][color=darkred]
                      >>> (Section 8.5, Initializers)
                      >>>
                      >>> So given
                      >>>
                      >>> struct data_t
                      >>> {
                      >>> int Idx;
                      >>> int Jdx;
                      >>> int Kdx;
                      >>> } data;
                      >>>
                      >>> data_t type is a POD class type (plain old data), so with empty
                      >>> parentheses, it should be zero-initialized.[/color]
                      >>
                      >> Assuming you are talking about the 1998 standard I don't think so. Look
                      >> up
                      >> the definition of compiler generated default constructor. I think you
                      >> will
                      >> see that it says Idx, Jdx and Kdx remain uninitialised not zero
                      >> initialised.
                      >>[/color]
                      > If I run test program below through Visual Studio 7.1. Then run said
                      > program through Borland C++ Builder 4. The end result. Builder 4 did
                      > zero initialize the struct while Visual Studio didn't.
                      >
                      >[/color]

                      Strange, my copy of VC++ 7.1 does zero initialise the struct. I thought
                      VC++ 7.1 was one of the few compilers to get this right.

                      john

                      Comment

                      • Neil Zanella

                        #12
                        Re: initializing static class variables

                        Given the contradictions making the 1998 and 2003 C++ standards clash
                        on this
                        particular issue I would expect that some older C++ programs would
                        malfunction
                        or even segfault when compiled with a newer compiler and then run by
                        the user.

                        In particular, several books seem to emphasize that programmers should
                        not document language features in their code. In this case, it seems
                        it
                        could be hard to spot where a particular program is relying on some
                        feature
                        from the 1998 standard that makes it behave differently in the 2003
                        standard.

                        In any case, I have not come across any books that discuss the
                        differences
                        between default initialization and value initialization, not even
                        older books.
                        Does anyone know of any C++ books (i.e. not the standard itself) that
                        actually
                        mention this issue? If so I would be interested in knowing which ones,
                        as it
                        seems to me that default versus value initialization is somewhat of an
                        advanced topic (not having seen it in any C++ book).

                        I wonder how many people actually rely on it (perhaps not even knowing
                        it).

                        So, elaborating on the example posted by John Harrison, what does the
                        2003 standard say about the following example? In particular, is it
                        possible to
                        default initialize instances of Bar and FooBar in the same way, and
                        how
                        does the 2003 standard say it should be done if possible to do so?

                        #include <iostream>
                        using namespace std;

                        struct Foo
                        {
                        int x;
                        };

                        struct Bar
                        {
                        Bar(): x(10) { }
                        int x;
                        }

                        struct FooBar
                        {
                        Bar(int x): x(x) { }
                        int x;
                        }

                        int main()
                        {
                        int* a = new int;
                        cout << *a << '\n';
                        int* b = new int();
                        cout << *b << '\n';
                        Foo* c = new Foo;
                        cout << c->x << '\n';
                        Foo* d = new Foo();
                        cout << d->x << '\n';
                        }

                        Thanks,

                        Neil

                        "John Harrison" <john_andronicu s@hotmail.com> wrote in message
                        [color=blue][color=green]
                        > > The 1998 standard for C++ (ISO/IEC 14882-1998) says:
                        > >
                        > > "An object whose initializer is an empty set of parentheses, i.e., (),
                        > > shall be default-initialized."[/color]
                        >
                        > That's directly contradicted by the 2003 standard which says value
                        > initialised.
                        >
                        > And that's the crucial difference, because value initialisation does not
                        > use the compiler generated default constructor.
                        >
                        > john[/color]

                        Comment

                        Working...