Nifty/Schwarz counter, standard compliant?

情到浓时终转凉″ 提交于 2019-11-28 23:20:20

I believe it's guaranteed to work. According to the standard ($3.6.2/1): "Objects with static storage duration (3.7.1) shall be zero-initialized (8.5) before any other initialization takes place."

Since nifty_counter has static storage duration, it gets initialized before initializer is created, regardless of distribution across translation units.

Edit: After rereading the section in question, and considering input from @Tadeusz Kopec's comment, I'm less certain about whether it's well defined as it stands right now, but it is quite trivial to ensure that it is well-defined: remove the initialization from the definition of nifty_counter, so it looks like:

static int nifty_counter;

Since it has static storage duration, it will be zero-initialized, even without specifying an intializer -- and removing the initializer removes any doubt about any other initialization taking place after the zero-initialization.

I think missing from this example is how the construction of Stream is avoided, this often is non-portable. Besides the nifty counter the initialisers role is to construct something like:

extern Stream in;

Where one compilation unit has the memory associated with that object, whether there is some special constructor before the in-place new operator is used, or in the cases I've seen the memory is allocated in another way to avoid any conflicts. It seems to me that is there is a no-op constructor on this stream then the ordering of whether the initialiser is called first or the no-op constructor is not defined.

To allocate an area of bytes is often non-portable for example for gnu iostream the space for cin is defined as:

typedef char fake_istream[sizeof(istream)] __attribute__ ((aligned(__alignof__(istream))))
...
fake_istream cin;

llvm uses:

_ALIGNAS_TYPE (__stdinbuf<char> ) static char __cin [sizeof(__stdinbuf <char>)];

Both make certain assumption about the space needed for the object. Where the Schwarz Counter initialises with a placement new:

new (&cin) istream(&buf)

Practically this doesn't look that portable.

I've noticed that some compilers like gnu, microsoft and AIX do have compiler extensions to influence static initialiser order:

  • For Gnu this is: Enable the init-priority with the -f flag and use __attribute__ ((init_priority (n))).
  • On windows with a microsoft compiler there is a #pragma (http://support.microsoft.com/kb/104248)
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!