C++ 匿名union的一个问题

图片描述图片描述

匿名union不能含有成员函数,此时如果匿名union中含有string类型的成员(此时匿名union会生成删除的对应的操作)
如果匿名union嵌套在其他类当中,这个类管理着union类类型的成员的状态,但是union对应的拷贝控制成员都是删除的,嵌套的类对应的成员也应该是删除的(因为匿名union中未定义拷贝操作)
,下面这个类为什么可以?

图片描述

阅读 3.7k
1 个回答
嵌套的类对应的成员也应该是删除的

这只是说如果没有提供,默认实现会是 =delete 。但是,这不能阻止显式提供自己的版本。

而且,这种情况下,由于默认的版本不可用,如果想拷贝/赋值等等,必须自己显式地实现自己的版本。

你必须在 Token 的拷贝构造函数(或其他成员中),决定如何拷贝(或进行其他对应操作)其中的匿名 union 。

=============

“删除的”引起了很多误解,这里澄清一下。仅以拷贝构造为例。
C++17 15.8.1 Copy/move constructors

6 If the class definition does not explicitly declare a copy constructor, a non-explicit one is declared implicitly. If the class definition declares a move constructor or move assignment operator, the implicitly declared copy constructor is defined as deleted; otherwise, it is defined as defaulted (11.4). The latter case is deprecated if the class has a user-declared copy assignment operator or a user-declared destructor

10 An implicitly-declared copy/move constructor is an inline public member of its class. A defaulted copy/move constructor for a class X is defined as deleted (11.4.3) if X has:

(10.1) — a variant member with a non-trivial corresponding constructor and X is a union-like class,
(10.2) — a potentially constructed subobject type M (or array thereof) that cannot be copied/moved because overload resolution (16.3), as applied to find M’s corresponding constructor, results in an ambiguity or a function that is deleted or inaccessible from the defaulted constructor,
(10.3) — any potentially constructed subobject of a type with a destructor that is deleted or inaccessible from the defaulted constructor, or,
(10.4) — for the copy constructor, a non-static data member of rvalue reference type.

A defaulted move constructor that is defined as deleted is ignored by overload resolution (16.3, 16.4).

这里说的很清楚了,只用但没有显式实现的时候,才会默认实现。而默认实现在某些情况下是 deleted 。

而不是直接删除了这个函数,在没有实现的能力。

只要有显式地实现,那么,默认实现(=delete)是不生效的。

当然,这个说的是 Token 类。

==================
后上传的图片(Class A, Class B) 中的问题跟开始的感觉还不太一样,这个设计到一个包含 union 的类怎么析构的问题。

class A 里的不是匿名 union ,它有一个 union 类型的成员。这个成员没有析构函数。class B 里的才是匿名 union。

对 destructor,有如下规定:C++17 15.4 Destructors

9 After executing the body of the destructor and destroying any automatic objects allocated within the body, a destructor for class X calls the destructors for X’s direct non-variant non-static data members, the destructors for X’s non-virtual direct base classes and, if X is the type of the most derived class (15.6.2), its destructor calls the destructors for X’s virtual base classes.

一个析构函数,函数执行完之后,要对成员及基类进行析构。只是,成员析构仅会对 non-variant non-static 进行。

Class A 中的成员 A::z 的类型的 union F,这不是一个匿名 union 。 A::z 是一个 non-variant non-static 成员,因而它必须提供自己的析构函数(因为没有默认的,或者说默认的是 =delete),否则 A 的析构就不能完成(A析构是会调用 A::z 的析构)。

但是 B 中确实是一个匿名 union ,这个匿名 union 仅引入了一个 variant member B::f ,在 B 析构的时候,不会调用 variant member B::f 的析构。(B::f 如果需要析构,必须在 ~B 的函数体里显式地进行)。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题