Example on how to access the value of an object th

2019-08-30 18:16发布

问题:

3.10/10

If a program attempts to access the stored value of an object through a glvalue of other than one of the following types the behavior is undefined:

  • the dynamic type of the object,
  • a cv-qualified version of the dynamic type of the object,
  • a type similar (as defined in 4.4) to the dynamic type of the object,
  • a type that is the signed or unsigned type corresponding to the dynamic type of the object,
  • a type that is the signed or unsigned type corresponding to a cv-qualified version of the dynamic type of the object,
  • an aggregate or union type that includes one of the aforementioned types among its elements or nonstatic data members (including, recursively, an element or non-static data member of a subaggregate or contained union),
  • a type that is a (possibly cv-qualified) base class type of the dynamic type of the object,
  • a char or unsigned char type.

回答1:

Readers should be aware that the paragraph cited by the OP is a religious issue, as the basis of a disputed behavior of the g++ compiler. Any answer sowing doubt on the accuracy or completeness of this paragraph (and it's neither) will generally get downvoted on SO.

Here's an example of UB according to the paragraph you're citing:

struct X { int i; };

auto main() -> int
{
    X o{ 0 };
    return reinterpret_cast<int&>( o );
}

Considering each possibility in C++11 §3.10/10 in order:

  • Is “the dynamic type of the object” o an int?
    No, the dynamic type is an X.

  • Is int perhaps “a cv-qualified version” of the dynamic type X?
    No, X is not an int, cv-qualified or not.

  • Is int “a type similar (as defined in 4.4) to the dynamic type of the object”?
    Again, no. 4.4 deals with multi-level cv-qualification.

  • Well, is int “a type that is the signed or unsigned type corresponding to the dynamic type of the object”?
    No, there are no signed or unsigned versions of a class type like X.

  • So what about “a type that is the signed or unsigned type corresponding to a cv-qualified version of the dynamic type of the object”?
    No.

  • Well, is int perhaps “an aggregate or union type that includes one of the aforementioned types among its elements or nonstatic data members (including, recursively, an element or non-static data member of a subaggregate or contained union)”?
    No, not that either.

  • So maybe int is “a type that is a (possibly cv-qualified) base class type of the dynamic type of the object”?
    No, an int can’t be a base class.

  • Finally, is int “a char or unsigned char type”?
    No.

And this exhausts all possibilities, proving that according to that paragraph in isolation, this code has Undefined Behavior.

However, this code is guaranteed to work by another part of the standard (I guess mainly for C compatibility).

So, the paragraph you cite isn't 100% good even for the completely platform-independent formal.


Edit: "dyp" asked in a comment how this relates to use of an xvalue. An xvalue is a glvalue, so one can just substitute an xvalue for the lvalue expression o. An example of such xvalue is an rvalue reference returned from a function, e.g. from std::move:

#include <utility>
using std::move;

struct X { int i; };

template< class T >
auto ref( T&& r ) -> T& { return r; }

auto main() -> int
{
    X o{ 0 };
    return reinterpret_cast<int&>( ref( move( o ) ) );
}

All this does is however to mask the essentials.