0

http://ideone.com/1ohrsO

The push_back called inside the constructor of static_constructor, is not reflected. Why?

#include <iostream>
#include <vector>
#include<memory>
#include<string>

using namespace std;

class has_static_constructor
{
    public:
    friend class static_constructor;
    static vector<int> v;



         class static_constructor
        {
            public:

             vector<int> * upt; //&v;
            static_constructor()
            {
                cout<<"inside static_constructor";
                upt = &has_static_constructor::v;
                has_static_constructor::v.push_back(1);
                has_static_constructor::v.push_back(20);
            }

        } ;

        static std::unique_ptr<has_static_constructor::static_constructor> upt ;
};



unique_ptr<has_static_constructor::static_constructor> has_static_constructor::upt(new has_static_constructor::static_constructor());

vector< int > has_static_constructor::v(2,100);

int main() {
    // your code goes here

    for (std::vector<int>::const_iterator i = has_static_constructor::v.begin(); i != has_static_constructor::v.end(); ++i)
    {   std::cout << *i << ' ';
        cout<<"\n I was here\n";
    }

    return 0;
}

Output:

inside static_constructor100 
 I was here
100 
 I was here
q126y
  • 1,589
  • 4
  • 18
  • 50
  • what problem are you actually trying to solve. There is without doubt already a well-known solution. – Richard Hodges Nov 01 '15 at 10:48
  • 1
    It is better to post code within your post, rather than linking to code on another site that might disappear. In any event, the constructor of your class `static_constructor` is accessing a static member of `has_static_constructor` before that member is constructed. The result of doing that is undefined behaviour according to the C++ standard. That means any behaviour is acceptable, including what you are seeing. – Peter Nov 01 '15 at 10:53
  • @Peter `upt = &has_static_constructor::v;` inside `static_constructor()`, should initialize `v`, before `push_back()` is called. Am I missing something? – q126y Nov 01 '15 at 10:55
  • @RichardHodges I am just trying to implement static constructor in C++, out of curiosity. I am learning the language. – q126y Nov 01 '15 at 10:56
  • 1
    @q: it is the order of the definitions of those statics (since they are all in one compilation unit) not the order of their declarations within the class definitions. Although you've updated your post, you left out the definitions of the statics that was in the code you linked to. – Peter Nov 01 '15 at 11:15

2 Answers2

3

static_constructor() is called before has_static_constructor::v initialization.

Move

unique_ptr<has_static_constructor::static_constructor> has_static_constructor::upt(new has_static_constructor::static_constructor());

after

vector< int > has_static_constructor::v(2,100);

to have expected behaviour.

But better avoid those global entirely.

Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • your suggestion works, but `upt = &has_static_constructor::v;` inside `static_constructor()`, should initialize `v`, before `push_back()` is called, so my original code should work, too. Am I missing something? – q126y Nov 01 '15 at 10:52
  • @q126y Why do you expect an assignment to `upt` to initialise `v`? – Konrad Rudolph Nov 01 '15 at 11:07
  • @KonradRudolph Actually I was trying to implement what you said in comment here http://stackoverflow.com/questions/5803953/static-constructor-in-c > @Tod Very valid comment. Unfortunately, having lazy loading is quite a > bit more complicated. Essentially I would solve it with a static > unique_ptr to a nested class which holds all the “static” members as, > in fact, non-static members, and which is initialised to 0 and reset > to a valid pointer once it’s first accessed. I thought, accessing `v`, would force the program to look up for it, and initialize it. – q126y Nov 01 '15 at 11:11
0

You might want to have a look at this way of ordering the code. It removes all initialisation-order dependencies, and in my view neatly separates the public interface from the internal implementation of the static data.

#include <iostream>
#include <vector>


class has_static_constructor
{
    // note - all private

    struct static_data {
        static_data()
        : _v(2, 100)
        {
            _v.push_back(1);
            _v.push_back(20);
        }
        std::vector<int> _v;
    };

    static static_data& statics() {
        static static_data sd;
        return sd;
    }

    // public interface
public:

    static std::vector<int>& v() { return statics()._v; }

};

auto main() -> int
{
    for (const auto& i : has_static_constructor::v())
    {
        std::cout << i << std::endl;
    }
    return 0;
}

expected output:

100
100
1
20
Richard Hodges
  • 68,278
  • 7
  • 90
  • 142