Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to Initialize a static member array dynamically

There are so many questions about initializing static members in C++, and yet I couldn't find this one.

class Node {

  private:
    static const int INITIAL_SIZE = 100;
    static Node* node_space;
    static int OUT_OF_BOUNDS = 0;
    static Node BAD_NODE;

};

Node* Node::node_space = new Node[Node::INITIAL_SIZE];

This seems to work, but I also want to add BAD_NODE to this array as the first element.

Node Node::BAD_NODE = Node();
Node::node_space[OUT_OF_BOUNDS] = BAD_NODE;

The above doesn't compile. The message is

Node.cpp:7: error: expected constructor, destructor, or type conversion before '=' token

This is for a school project in which we are implementing a linked list with an array.

like image 449
Ziggy Avatar asked Nov 04 '22 14:11

Ziggy


2 Answers

What you may want to-do here, if you only have a single static data-object, but you want to dynamically initialize it, is to create a singleton object as a wrapper around your Node class. Basically what occurs with a singleton is you create a single version of a class that is initialized with a normal class constructor, but the constructor, operator=(), and copy-constructor are declared private. Then a single static version of the class is created through a static variable, and there is a public accessor method that allows other portions of your code to access the singleton class (i.e., the accessor returns either a reference or constant reference to the static class you created).

class Node_S
{
    private:

        //your original Node class we're wrapping in the singleton object
        struct Node {
            static const int INITIAL_SIZE = 100;
            static Node* node_space;
            static int OUT_OF_BOUNDS;
            static Node BAD_NODE;
        };

        //private default constructor is only called once
        Node_S()
        {
            //place your original initialization code for Node here
            Node::OUT_OF_BOUNDS = 0;
            Node::node_space = new Node[Node::INITIAL_SIZE];
            Node::BAD_NODE = Node();
            Node::node_space[Node::OUT_OF_BOUNDS] = Node::BAD_NODE;
        }

        //private copy and assignment operator
        Node_S(const Node_S&) {}
        Node_S& operator=(const Node_S&) { return *this; }

    public:

        static Node_S& get_instance() 
        {
            //here is where the single version of Node_S is created
            //at runtime
            static Node_S singleton_instance = Node_S();
            return singleton_instance;
        }

        //... Other public functions
};

Now you would access your singleton via Node_S::get_instance(). Since the copy and assignment operators are declared private, you cannot create extra copies of your singleton ... there will only be a single instance of this class created. If you needed to pass it around, you would do-so by reference. Furthermore there is no initialization ambiguity because all the static elements of Node are initialized in-order during run-time when get_instance() is called. Since singleton_instance is a static variable, the number of times the constructor Node_S() is run is only once, so you can basically place all your initialization code for Node safely inside of the constructor. Then simply add any additional methods required to work with the Node type in your Node_S interface. So some common usage code might look like the following:

Node_S::Node a_node_copy = Node_S::get_instance().get_node(10);
like image 141
Jason Avatar answered Nov 15 '22 00:11

Jason


In C++11 (i.e "in C++" :-)), you can provide an initialization list for arrays:

Node* Node::node_space = new Node[Node::INITIAL_SIZE] { Node::BAD_NODE };

This will only work if you mean to set the first element to something specific. The initialization list has to provide the initial sequence of elements, so it's not clear what those would be if OUT_OF_BOUNDS wasn't zero.

like image 32
Kerrek SB Avatar answered Nov 15 '22 00:11

Kerrek SB