Search code examples
c++11member-initialization

C++0x Member initialization without a constructor


In N3257 I found an example using initializing members without a constructor, which is fine. I guess that is possible, because it is a POD.

template<typename T>
struct adaptor {
    NonStdContainer<T>* ptr;                // <- data member
    T* begin() { return ptr->getFirst(); }
    T* end() { return ptr->getLast() + 1; }
};
void f(NonStdContainer<int>& c) {
    for (auto i : adaptor<int>{&c})         // <- init
        { /* ... */ }
}

When I played around with this example I replaced the * with a &, because I don't like raw pointers:

template<typename T>
struct adaptor {
    NonStdContainer<T>& ptr;                // <- data member, now REF
    T* begin() { return ptr->getFirst(); }
    T* end() { return ptr->getLast() + 1; }
};
void f(NonStdContainer<int>& c) {
    for (auto i : adaptor<int>{c})         // <- init
        { /* ... */ }
}

This was fine and compiled without warning with GCC-4.7.0.

Then I got curious about the initialization of PODs and what might have changed with C++0x. There I found Bjarnes FAQ. He says there that PODs may contain pointers, but no references.

Ops, now I wonder:

  • Do I have non-POD-object here, which the compiler can initialize without a constructor anyway and I just miss which mechanisms are used here?
  • or Is the GCC-4.7.0 behaving non-std by letting me initializing the ref this way?
  • or has there been a change in the std since Bjarnes FAQ that also allows references in PODs?

Update: I found aggregates in the current std (8.5.1 Aggregates [dcl.init.aggr]), but references are not mentioned there, so I am not sure how they relate to this


Solution

  • Quoting the standard [dcl.init.aggr]:

    An aggregate is an array or a class (Clause 9) with no user-provided constructors (12.1), no brace-or-equal- initializers for non-static data members (9.2), no private or protected non-static data members (Clause 11), no base classes (Clause 10), and no virtual functions (10.3).

    When an aggregate is initialized by an initializer list, as specified in 8.5.4, the elements of the initializer list are taken as initializers for the members of the aggregate, in increasing subscript or member order. Each member is copy-initialized from the corresponding initializer-clause...

    That means you have an aggregate here, aggregates can be initialized how you do it. PODs have nothing to do with it, they are really meant for communication with eg. C.

    Copy-initialization of a reference with a variable is certainly legal, because that just means

    T& ref = c;
    

    Do I have non-POD-object here, which the compiler can initialize without a constructor anyway and I just miss which mechanisms are used here?

    Yes, the object is non-POD.

    Is the GCC-4.7.0 behaving non-std by letting me initializing the ref this way?

    No.