3

Test.h

class Test
{
    static int i;
};

Test.cpp

int Test::i = 1;

I know that normally we initialize a static member as above. And the static member is initialized before the function main runs.
My question is:
Is it possible to initialize the static member after the function main runs? Something like this:

int main()
{
// do something
// initialize the Test::i here
}
Yves
  • 11,597
  • 17
  • 83
  • 180

4 Answers4

1

No, it isn't possible to initialize it, but there should be no reason why you can't just call a static setter function that assigns a value to i in run-time. This is the best method.

Or you alternatively, you could make it so that the constructor always initializes the variable:

#include <iostream>

class Test
{
  private:
    static int i;

  public:
    Test()
    {
      i=2;
    }

    void print_i (void)
    {
      std::cout << i << std::endl;
    }
};

int Test::i = 1;


int main()
{
  Test test;

  test.print_i(); // will print 2
}
Lundin
  • 195,001
  • 40
  • 254
  • 396
  • OK. I know what you mean. Btw, you can't initialize the static member in the constructor. :D – Yves May 05 '15 at 08:59
  • 1
    @Thomas It is not initialization, it is run-time assignment. Initialization would have been `Test() :i(2) {}` which will indeed not work. – Lundin May 05 '15 at 09:00
  • oh. Sorry I misunderstand. You do "assignment" in the constructor, not initialization. OK, got you. – Yves May 05 '15 at 09:01
  • @Thomas Note however that the above will cause problems if you declare an object to the class static/global. So it is not ideal. The best solution is to use a setter function. – Lundin May 05 '15 at 09:02
  • While "it isn't possible to initialize it" is true when taken literally I think Wintermute provided an as-if solution which effectively does exactly that. – Peter - Reinstate Monica May 05 '15 at 09:15
1

I'm going to assume that you really mean initialization, so that assignment after main has started is out. This will not make a difference for basic types like int or double, but may make one for complex data types.

The answer is: no but yes (sort of). It is not possible to delay the initialisation of a static data member until after main started, but you can use a static member function with a function-local static object to simulate the effect. This object will be initialized after the function is first called. In code:

#include <iostream>

struct A {
  A() {
    std::cout << "A::A()\n";
  }

  void do_something() {
    std::cout << "A::do_something()\n";
  }
};

struct B {
  static A &a() {
    static A instance;
    return instance;
  }
};

int main() {
  std::cout << "main start\n";

  B::a().do_something();
  B::a().do_something();

  std::cout << "main end\n";
}

This will print

main start
A::A()
A::do_something()
A::do_something()
main end

You would then use B::a() where you'd have used B::a before. You will have to make sure that the function is not called before main is started.

Wintermute
  • 42,983
  • 5
  • 77
  • 80
0

The first mistake you have is that the variable 'i' is private for the class, so you cannot access it outside the class. There are two ways to fix this. The first is to make it public(not preffered) and the second to make setter and getter methods.

About the question the answer is yes, you can. Use the setter method I mentioned above. These are the two methods:

//…
public:
  static int get_i() {
    return i;
  }
  static void set_i(int val) {
    i = val;
  }
//…

You can call the method like that:

Test::set_i(10);

Note: do not forget to include the keyword public before the methods so you can access them outside the class.

anakin
  • 551
  • 4
  • 12
  • I don't think he was trying to access it. He is only asking for initialization which is not related with access modifiers. I don't think your getter is initializing the variable. You are only reassigning the new value to i. – user258367 May 05 '15 at 09:03
-1

You're confusing the word static and the word const.

You have to initialize a const when you declare it;

You don't have to initialize a static when you declare it, but you can change it anywhere anytime, given you can access it. (which is not the case here, your i is private.)

About thoses statements, let's look at the C++ standard (3.6.2) :

Variables with static storage duration or thread storage duration shall be zero-initialized before any other initialization takes place.

Technically, yes, your static data is always zero-initialized even if you explicitely initialize it.

Mekap
  • 2,065
  • 14
  • 26
  • If you don't initialize the static explicitly, it will however still get initialized to zero, which is required by the standard. There's no way to dodge where the static initialization takes place: it is always done before main() is executed. – Lundin May 05 '15 at 08:59
  • @Lundin I don't agree, even if you initialize your static explicitely it still gets zero-initalized; but i've made my answer more clearer to illustrate why.. – Mekap May 05 '15 at 09:05
  • As usual downvoters, if you feeli like something should be improved, take a sec' and explain what. – Mekap May 05 '15 at 09:17
  • (I didn't down vote) No, if you initialize your static explicitly it gets initialized to that value and gets allocated in the `.data` segment. If you don't initialize it explicitly, it gets initialized to zero and gets allocated in the `.bss` segment. The text you quote merely means that static initialization occurs before what the standard calls "dynamic initialization". – Lundin May 05 '15 at 09:33
  • @Lundi according to the C++ Standard, static data gets **always** zero-initalized, no matter what happens after. – Mekap May 05 '15 at 09:36
  • `Objects with static storage duration (3.7.1) shall be zero-initialized (8.5) before any other initialization takes place. Zero-initialization and initialization with a constant expression are collectively called static initialization; all other initialization is dynamic initialization.` This doesn't mean that the object gets initialized to zero first and then to something else, it just means that zero initialization occurs first in the order of initialization. – Lundin May 05 '15 at 09:39
  • Or maybe it doesn't... http://stackoverflow.com/questions/24496795/example-static-and-dynamic-initialization. Whenever I assume that C++ behave in the same sane manner as C, the C++ standard proves me wrong. – Lundin May 05 '15 at 09:43
  • @Lundin Yup, that's why i was asking myself how my answer could be improved, i don't know. But hey at least you learned somethin', so mission accomplished :D – Mekap May 05 '15 at 09:49
  • 1
    Sometimes I think the only sane guy in the C++ standard committee who stood up on day one and said "but it doesn't make sense!" got executed right then and there, and then the merry work could continue and various substances could be smoked without protests. – Lundin May 05 '15 at 09:51
  • @Lundin i mean i'm still trying to figure out why, don't get me wrong. Maybe there's that one scenario where you need to set before resetting ... Welp. – Mekap May 05 '15 at 09:52