Initializing a union with a non-trivial constructor

前端 未结 6 2032
野性不改
野性不改 2020-11-30 00:30

I have a structure which I create a custom constructor to initialize the members to 0\'s. I\'ve seen in older compilers that when in release mode, without doing a memset to

相关标签:
6条回答
  • 2020-11-30 00:44

    Question 1: Default constructors do initialize POD members to 0 according to the C++ standard. See the quoted text below.

    Question 2: If a constructor must be specified in a base class, then that class cannot be part of a union.

    Finally, you can provide a constructor for your union:

    union U 
    {
       A a;
       B b;
    
       U() { memset( this, 0, sizeof( U ) ); }
    };
    

    For Q1:

    From C++03, 12.1 Constructors, pg 190

    The implicitly-defined default constructor performs the set of initializations of the class that would be performed by a user-written default constructor for that class with an empty mem-initializer-list (12.6.2) and an empty function body.

    From C++03, 8.5 Initializers, pg 145

    To default-initialize an object of type T means:

    • if T is a non-POD class type (clause 9), the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor);
    • if T is an array type, each element is default-initialized;
    • otherwise, the object is zero-initialized.

    To zero-initialize an object of type T means:

    • if T is a scalar type (3.9), the object is set to the value of 0 (zero) converted to T;
    • if T is a non-union class type, each non static data member and each base-class subobject is zero-initialized;
    • if T is a union type, the object’s first named data member is zero-initialized;
    • if T is an array type, each element is zero-initialized;
    • if T is a reference type, no initialization is performed.

    For Q2:

    From C++03, 12.1 Constructors, pg 190

    A constructor is trivial if it is an implicitly-declared default constructor and if:

    • its class has no virtual functions (10.3) and no virtual base classes (10.1), and
    • all the direct base classes of its class have trivial constructors, and
    • for all the nonstatic data members of its class that are of class type (or array thereof), each such class has a trivial constructor

    From C++03, 9.5 Unions, pg 162

    A union can have member functions (including constructors and destructors), but not virtual (10.3) functions. A union shall not have base classes. A union shall not be used as a base class.An object of a class with a non-trivial constructor (12.1), a non-trivial copy constructor (12.8), a non-trivial destructor (12.4), or a non-trivial copy assignment operator (13.5.3, 12.8) cannot be a member of a union, nor can an array of such objects

    0 讨论(0)
  • 2020-11-30 00:45

    Things changed for the better in C++11.

    You can now legally do this, as described by Stroustrup himself (I reached that link from the Wikipedia article on C++11).

    The example on Wikipedia is as follows:

    #include <new> // Required for placement 'new'.
    
    struct Point {
        Point() {}
        Point(int x, int y): x_(x), y_(y) {}
        int x_, y_;
    };
    
    union U {
        int z;
        double w;
        Point p; // Illegal in C++03; legal in C++11.
        U() {new(&p) Point();} // Due to the Point member, a constructor
                               // definition is now *required*.
    };
    

    Stroustrup goes into a little more detail.

    0 讨论(0)
  • 2020-11-30 00:54

    As mentioned in Greg Rogers' comment to unwesen's post, you can give your union a constructor (and destructor if you wish):

    struct foo
    {
        int a;
        int b;
    };
    
    union bar
    {
        bar() { memset(this, 0, sizeof(*this)); }
    
        int a;
        foo f;
    };
    
    0 讨论(0)
  • 2020-11-30 00:56

    AFAIK union members may not have constructors or destructors.

    Question 1: no, there's no such guarantee. Any POD-member not in the constructor's initialization list gets default-initialized, but that's with a constructor you define, and has an initializer list. If you don't define a constructor, or you define a constructor without an initializer list and empty body, POD-members will not be initialized.

    Non-POD members will always be constructed via their default constructor, which if synthesized, again would not initialize POD-members. Given that union members may not have constructors, you'd pretty much be guaranteed that POD-members of structs in a union will not be initialized.

    Question 2: you can always initialize structures/unions like so:

    struct foo
    {
        int a;
        int b;
    };
    
    union bar
    {
        int a;
        foo f;
    };
    
    bar b = { 0 };
    
    0 讨论(0)
  • 2020-11-30 01:07

    You'll have to wait for C++0x to be supported by compilers to get this. Until then, sorry.

    0 讨论(0)
  • 2020-11-30 01:09

    Can you do something like this?

    class Outer
    {
    public:
        Outer()
        {
            memset(&inner_, 0, sizeof(inner_));
        }
    private:
        union Inner
        {
            int qty_;
            double price_;
        } inner_;
    };
    

    ...or maybe something like this?

    union MyUnion
    {
        int qty_;
        double price_;
    };
    
    void someFunction()
    {
        MyUnion u = {0};
    }
    
    0 讨论(0)
提交回复
热议问题