Can we access a member of a non-existing union?

你。 提交于 2019-12-05 09:32:27

[expr.ref]/4.2 defines what E1.E2 means if E2 is a non-static data member:

If E2 is a non-static data member [...], the expression designates the named member of the object designated by the first expression.

This defines behavior only for the case where the first expression actually designates an object. Since in your example the first expression designates no object, the behavior is undefined by omission; see [defns.undefined] ("Undefined behavior may be expected when this document omits any explicit definition of behavior...").


You are also misinterpreting what "access" means in the strict aliasing rule. It means "read or modify the value of an object" ([defns.access]). A class member access expression naming a non-static data member neither reads nor modifies the value of any object and therefore is not an "access", and therefore there's never an "access ... through" a glvalue of "an aggregate or union type" by reason of a class member access expression.

[basic.lval]/11.6 is essentially copied from C, where it actually meant something because assigning or copying a struct or union accesses the object as a whole. It's meaningless in C++ because assignment and copying of class types are performed through special member functions that either performs memberwise copying (and so "accesses" the members individually) or operates on the object representation. See core issue 2051.

There are many situations, especially involving type punning and unions, where one part of the C or C++ Standard describes the behavior of some action, another part describes an overlapping class of actions as invoking UB, and the area of overlap includes some actions which should be processed consistently by all implementations as well as others that would be impractical to support on at least some implementations. Rather than trying to fully describe all cases that should be treated as defined, the authors of the Standard expected that implementations would seek to uphold the Spirit of C described in the Rationale, including the principle "Don't prevent the programmer from doing what needs to be done". This would generally lead to quality implementations giving priority to the definition of behavior when necessary to meet their customer's needs, while giving priority to the "undefinition" of behavior when that would allow optimizations that also serve their customer's needs.

The only way to treat the C or C++ Standard as defining a useful language is to recognize a category of actions whose behavior is described by one part of the Standard and classified as UB by another, and recognizing the treatment of actions in that category as a Quality of Implementation issue outside the jurisdiction of the Standard. The authors of the Standard expected compiler writers to be sensitive to their customers' needs, and thus didn't see conflicts between behavioral definitions and undefinitions as a particular problem. They thus saw no need to define terms like "object", "lvalue", "lifetime", and "access" in ways that could be applied consistently without creating such conflicts, and the definitions they created are thus not usable for purposes of deciding whether or not particular actions should be defined when such conflicts exist.

Consequently, unless or until the Standards recognize more concepts associated with objects and ways of accessing them, the question of whether a quality implementation intended to be suitable for some purpose should be expected to support a certain action will depend upon whether its authors should be expected to recognize that the action would be useful for such purpose.

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