Unions in C++11: default constructor seems to be deleted

我的未来我决定 提交于 2019-12-04 17:43:35

问题


I am trying to understand how unions were extended by C++11. One thing that changed is the ability to use now non-static data members with non-trivial special member functions. From cppreference.com

If a union contains a non-static data member with a non-trivial special member function (default constructor, copy/move constructor, copy/move assignment, or destructor), that function is deleted by default in the union and needs to be defined explicitly by the programmer. At most one data member can have a default member initializer.

I am trying the following code:

struct X
{
    ~X() {};
};

union U
{
    X x;
    ~U() {};
};

int main()
{
    U s1{};  // works, probably aggregate initialization
    U s2;    // DOES NOT compile, why?
}

Live on Coliru

Here X (which is used as a data member of the union) has a user provided destructor, hence the destructor of the union is by default deleted. Therefore I provide one explicitly. However, the code fails to compile, with the error

note: 'U::U()' is implicitly deleted because the default definition would be ill-formed:

The code compiles if I remove the last line U s2;.

Question What is going on here? Why U s1{}; compiles, but U s2; does not? Is the default ctor of the union marked as deleted (if so, why?!), and in the first case we have just aggregate initialization? Note that if I provide U(){}; // not U() = default; the code compiles (but not if I only provide a ctor of X).

EDIT

After digging into the standard (N4527):

Unions: 9.5/2 [class.union]

[Note: If any non-static data member of a union has a non-trivial default constructor (12.1), copy constructor (12.8), move constructor (12.8), copy assignment operator (12.8), move assignment operator (12.8), or destructor (12.4), the corresponding member function of the union must be user-provided or it will be implicitly deleted (8.4.3) for the union. —endnote]

it seems that this is a gcc bug (now reported here). The code compiles on clang and gcc 4.8.2 or earlier, it breaks on gcc4.9 and later (thanks @T.C. for pointing out).

Compiler: g++5.3, -std=c++11 used.


回答1:


The cppreference quote is unclear. What happens is that if ANY memeber of the union defines ANY of those non-trivial special member functions, then ALL of them will be deleted by default in the union.

So since you have a non-trivial destructor for X, the U default constructor is deleted.




回答2:


X is not a pod type because is not trivially copiable as it have destructor Also U is not a pod type.

U s2; try to call the default costructor that is deleted so the error

U s1 {}; use member wise initialization and don't call any costructor

In union with non pod member the default costructor of union is deleted because it would call the default costructor of members ie the compiler doesn't know which member to call the default costructor

 Union XX{
   string m1; 
   vector <int> m2;
}

default costructor of XX cannot call default costructor of m1 AND m2 so it is deleted



来源:https://stackoverflow.com/questions/34581372/unions-in-c11-default-constructor-seems-to-be-deleted

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!