2

Consider the following snippet:

extern "C" {
#include "POD.h" // Defines struct POD;
}

template<class Base>
struct non_copyable : Base
{
   non_copyable() {}

private:
   non_copyable(non_copyable const&);
   non_copyable& operator=(non_copyable const&);
};

class wrapper : non_copyable<POD>
{
   typedef non_copyable<POD> _base_t;

public:
   wrapper() : _base_t()
   {}
};

My attempt is to make sure that the base-class subobject POD is zero-initialized in all cases in C++03, C++11 and C++14, when creating local or temporary objects, static variables, by any of the syntactic flavours of new-expressions, etc. Also, I want to implement that in the simplest/shortest way as possible.

I believe that with the _base_t() initialization in wrapper's initializer-list I'm done, but I'm not fully sure if, since non_copyable has a user-defined default constructor, if initialization rules will be propagated from wrapper to POD, and thus, since I'm not explicity calling Base() in non_copyable's initializer-list, if it will be zero-initialized through the wrapper constructor in a standard conforming manner.

Also, I cannot use = default for the non-copyable's default constructor since wrapper must compile in C++03, so a user-defined constructor is mandatory here.

Some guidance in that? I'm a bit confused about the mess of initialization rules (which is a real thing: Default, value and zero initialization mess).

ABu
  • 10,423
  • 6
  • 52
  • 103
  • 1
    Not sure with all those rules in all language versions, but IIRC, `wrapper() : _base_t()` only ensures that the default constructor of `non_copyable` will be called. However, this constructor does not mention its `Base` subojbect (`POD` in your case) in its constructor member initializer list, which will result in its _default-initialization_. I would suggest to use `non_copyable() : Base() {}` instead, which should make the `Base` subobject _value-initialized_. – Daniel Langr May 08 '20 at 10:23
  • Yeah but that initialization is not a responsability of `non_copyable`. Maybe I will add an explicit conversion constructor from `Base` to non-copyable to initialize `Base` with a default constructed `Base`. I guess the optimizer will just replace all of this by a zero-initialization of Base. – ABu May 08 '20 at 10:45
  • 1
    _Default-constructed_ `Base` or _value-constructed_ `Base`? And, why it is not the responsibility of `non_copyable`? Why you cannot simply add `: Base()` to its constructor member initializer list? – Daniel Langr May 08 '20 at 12:49
  • 1
    BTW, this question might be relevant: [Force Default Initialized Constructor in POD?](https://stackoverflow.com/q/31495333/580083). – Daniel Langr May 08 '20 at 12:55
  • @DanielLangr Because you may want to not zero-initialize an object if you know for sure that it will be initialized with something different later. I want to zero-initialize it from `wrapper`, not from `non_copyable`. – ABu May 08 '20 at 13:13
  • Sorry, but I don't understand. Each object is initialized only and exactly once. It is not possible to initialize it once and "later" again. BTW, if I recall correctly, initialization of subobjects (including base objects) is the responsibility of direct derived class. You cannot initialize an indirect base (such as `Base` from `wrapper` in your case). – Daniel Langr May 08 '20 at 13:18
  • @DanielLangr Sorry, asign a value to it in a derived class constructor to change their values. From a point of view of someone creating an object of a derived class, the full object including their base-class subobjects are non-initialized until the derived class constructor finishes execution. The base-class subobjects are already initialized but that is only known to the derived class, not to the user creating objects of it. That's why I accidentally said "initializing it later". – ABu May 08 '20 at 13:23
  • 1
    Ok, I understand. But why do you care about possibly superfluous initialization/assignment? Is it for performance reasons? If so, I would trust your compiler optimization abilities a bit. If a compiler sees a "wasted" zero-initialization, it can completely optimize it away at the assembly level. See this [live example](https://godbolt.org/z/01lkyK), where with `-O3` optimization level, `i` is written only once instead of two times (as with `-O0`). – Daniel Langr May 08 '20 at 13:28
  • 1
    @DanielLangr Ok, you conviced me. Thanks. – ABu May 08 '20 at 13:44

0 Answers0