Thread: Regarding const array initialization

  1. #1
    Registered User
    Join Date
    Jul 2009
    Posts
    4

    Question Regarding const array initialization

    I am reading Thinking in C++, and meet a very strange problem regarding const array initialization. The content can be referred to page 356 and 357, for code C08: StringStack.cpp.

    part of the code:
    ---------------- (Code 1)
    Code:
    class StringStack {
      static const int size = 100;
      const string* stack[size]; // target to be discuss
      int index;
    public:
      StringStack();
      void push(const string* s);
      const string* pop();
    };
    
    StringStack::StringStack() : index(0){
      memset(stack, 0, size * sizeof(string*)); // initialization of point to const array
    }
    ....
    The book says, const (non-static) members must be initialized in initialization list of constructor before entering the constructor body. But what about the const string* stack[size]? it is not initialized before entering the constructor body.

    The more strange thing is, when I try to add a const int array, and do the similar thing:
    ----------------(Code 2)
    Code:
    class StringStack {
      static const int size = 100;
      const string* stack[size]; // target to be discuss
      const int z[size]; // newly added
      int index;
    public:
      StringStack();
      void push(const string* s);
      const string* pop();
    };
    
    StringStack::StringStack() : index(0){
      for(int i = 0; i < size: i ++){z[i] = i;} //try to initialize const int array
      memset(stack, 0, size * sizeof(string*)); // initialization of point to const array
    }
    ....

    the code will not compile (I am using VC++ 2008), and I am giving two error:
    error C2439: 'StringStack::z' : member could not be initialized
    error C2166: l-value specifies const object

    When I change the array to const int* z[size], it go back to work, even I don't initialize them int the constructor:
    ----------------(Code 3)
    Code:
    class StringStack {
      static const int size = 100;
      const string* stack[size]; // target to be discuss
      const int* z[size]; // change to pointer
      int index;
    public:
      StringStack();
      void push(const string* s);
      const string* pop();
    };
    
    StringStack::StringStack() : index(0){
      memset(stack, 0, size * sizeof(string*)); // initialization of point to const array
    }
    ....

    My question is:
    1. how to initialize a normal const array? I know adding static may solve the problem with external initialization, but my question is not that. More specific, how to made code 2 work?
    2. why we don't need to do explicit initialization for code 3? Actually if I don't add memset(stack, 0, size * sizeof(string*)); in the constructor, it will compile also. That means, initialize the array of pointers to const is different, but where is the initialization happens? by compiler?
    Last edited by codegeru; 07-18-2009 at 04:40 PM.

  2. #2
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Quote Originally Posted by codegeru View Post
    My question is:
    1. how to initialize a normal const array? I know adding static may solve the problem with external initialization, but my question is not that. More specific, how to made code 2 work?

    2. why we don't need to do explicit initialization for code 3? Actually if I don't add memset(stack, 0, size * sizeof(string*)); in the constructor, it will compile also. That means, initialize the array of pointers to const is different, but where is the initialization happens? by compiler?

    The only way to safely initialize a const array type is with the array initializer you should have learned when studying arrays. As the elements will not be messed with, you cannot assign values later. As far as the original code goes, if we look at its type, we can see why the memset call works.

    const string* stack[size] creates an array of pointers to const strings. In other words, the pointers can be reassigned, but the strings they point to are constant. Hence code that assigns all of the stack array elements to 0 (call to memset) is compilable.

  3. #3
    Registered User
    Join Date
    Jul 2009
    Posts
    4

    Question

    I agree for the explanation for
    Code:
     const string* stack[size]
    .
    Actually it create a normal array, not a const array. The only special thing is the elements of the array are pointers to const strings. So it needs not obey the rule that initialize it when define it for const member in class.

    But regarding for the first answer, I still don't get it. Where you put the array initializer? Outside the class? like z[size] = {0}? it does not work.


    Quote Originally Posted by whiteflags View Post
    The only way to safely initialize a const array type is with the array initializer you should have learned when studying arrays. As the elements will not be messed with, you cannot assign values later. As far as the original code goes, if we look at its type, we can see why the memset call works.

    const string* stack[size] creates an array of pointers to const strings. In other words, the pointers can be reassigned, but the strings they point to are constant. Hence code that assigns all of the stack array elements to 0 (call to memset) is compilable.

  4. #4
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    I've never had to use const arrays as class data. It's probably easier to use a container, such as a vector, and make that const.

    Then the code is like:

    Code:
    class Foo {
       private:
       static const int size = 100;
       const std::vector<int> z;
       
       public:
       explicit Foo(int *arrayIn);
    };
    
    Foo::Foo( const int *arrayIn ): z( arrayIn, arrayIn + size ) 
    {
       // constructor body
    }
    Because now you can call vector's constructor when it needs to be initialized in Foo's initializer list, and pass it ownership of some constant array.

  5. #5
    Registered User
    Join Date
    Jul 2009
    Posts
    4

    Question

    Yap, that will be a good alternative for the const array purpose in class.
    But the original problem still remains. Dose C++ allow the normal const array as the class member?

    Quote Originally Posted by whiteflags View Post
    I've never had to use const arrays as class data. It's probably easier to use a container, such as a vector, and make that const.

    Then the code is like:

    Code:
    class Foo {
       private:
       static const int size = 100;
       const std::vector<int> z;
       
       public:
       explicit Foo(int *arrayIn);
    };
    
    Foo::Foo( const int *arrayIn ): z( arrayIn, arrayIn + size ) 
    {
       // constructor body
    }
    Because now you can call vector's constructor when it needs to be initialized in Foo's initializer list, and pass it ownership of some constant array.

  6. #6
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    >> But the original problem still remains. Dose C++ allow the normal const array as the class member?

    Const members in classes need to be initialized in the initializer list of the constructor, (which basically means calling other constructors) and I don't think you can use an array initializer there. No.

  7. #7
    Registered User
    Join Date
    Jul 2009
    Posts
    4

    Thumbs up

    That sounds reasonable.

    Quote Originally Posted by whiteflags View Post
    >> But the original problem still remains. Dose C++ allow the normal const array as the class member?

    Const members in classes need to be initialized in the initializer list of the constructor, (which basically means calling other constructors) and I don't think you can use an array initializer there. No.

  8. #8
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Just to confirm what whiteflags said, there is no way to initialize an array member in the initializer list, which means you can't have a const array member.

    Initializer lists in C++0x should make it possible, I think.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 8
    Last Post: 04-25-2008, 02:45 PM
  2. Drawing Program
    By Max_Payne in forum C++ Programming
    Replies: 21
    Last Post: 12-21-2007, 05:34 PM
  3. matrix class
    By shuo in forum C++ Programming
    Replies: 2
    Last Post: 07-13-2007, 01:03 AM
  4. Quick question about SIGSEGV
    By Cikotic in forum C Programming
    Replies: 30
    Last Post: 07-01-2004, 07:48 PM
  5. Template Array Class
    By hpy_gilmore8 in forum C++ Programming
    Replies: 15
    Last Post: 04-11-2004, 11:15 PM

Tags for this Thread