Erik Wikström
10/3/2008 4:26:00 PM
On 2008-10-03 16:44, diamondback wrote:
> On Oct 3, 5:38 am, Bit Byter <takashi_...@hotmail.com> wrote:
>> I just realized that I cant use a union in an initialization list (or
>> at least not the way I tried to use it).
>>
>> This is what I did:
>>
>> class ValueObject
>> {
>> public:
>> ValueObject();
>> ValueObject(const ValueObject&);
>> ValueObject& operatr= (const ValueObject&);
>>
>> private:
>> union Item { int i, double d, char s[8]} m_item ;
>> enum { integer, Double, String } m_type ;
>>
>> };
>>
>> //impl:
>>
>> ValueObject():m_type(Integer), m_item.i(0) //<- compiler complains
>> {}
>>
>> ValueObject():m_type(Integer)//<- compiler ok with this - why?
>> {m_item.i(0);}
>
> Bit,
>
> I am not 100% sure on this one but I'll give it a shot.
> The difference between a member initialization list and assignments
> made in the constructor body is subtle but relevant. The items in the
> initialization list are constructed once. The items NOT in the
> initialization list are DEFAULT constructed then COPY constructed when
> assigned in the constructor body.
>
> Now enter Unions. A union is a struct with all of it's members
> assigned to the same memory location. Disclaimer: what follows is
> simply an educated guess on my part. I assume that union members are
> constructed using a placement-new type process, so all the members are
> declared starting in the same spot in memory. That means that they are
> probably constructed in the order that they are declared (ex. i, d,
> s, ...). So, after initializing m_item.i, the memory can be, depending
> on the implementation, re-initialized by the successive constructors.
> This would preclude initializing union members in an initialization
> list. All of the union members must be constructed before being
> assigned to, so the compiler does not support it.
Actually union members are not allowed to have non-trivial constructors
(which, I believe, limits the members to built-in types and PODs
containing built-in types). So the member are not, in practice,
initialised at all.
If you want to initialise members of a union you can add a constructor
to the union, which you can then use in the initialisation list:
union Foo
{
int i;
double d;
Foo(double v) : d(v) { }
};
class Bar
{
Foo f;
int i;
public:
Bar(int i, double d) : i(i), f(d) { }
};
int main()
{
Bar b(1, 4.5);
return 0;
}
--
Erik Wikström