开发者

In a class with no virtual methods or superclass, is it safe to assume (address of first member variable) == this?

开发者 https://www.devze.com 2022-12-27 03:33 出处:网络
I made a private API that assumes that the address of the first member-object in the class will be the same as the class\'s this-pointer... that way the member-object can trivially derive a pointer to

I made a private API that assumes that the address of the first member-object in the class will be the same as the class's this-pointer... that way the member-object can trivially derive a pointer to the object that it开发者_JS百科 is a member of, without having to store a pointer explicitly.

Given that I am willing to make sure that the container class won't inherit from any superclass, won't have any virtual methods, and that the member-object that does this trick will be the first member object declared, will that assumption hold valid for any C++ compiler, or do I need to use the offsetof() operator (or similar) to guarantee correctness?

To put it another way, the code below does what I expect under g++, but will it work everywhere?

class MyContainer
{
public:
   MyContainer() {}
   ~MyContainer() {}  // non-virtual dtor

private:
   class MyContained
   {
   public:
      MyContained() {}
      ~MyContained() {}

      // Given that the only place Contained objects are declared is m_contained
      // (below), will this work as expected on any C++ compiler?
      MyContainer * GetPointerToMyContainer()
      {
         return reinterpret_cast<MyContainer *>(this);
      }
   };

   MyContained m_contained;  // MUST BE FIRST MEMBER ITEM DECLARED IN MyContainer
   int m_foo;                // other member items may be declared after m_contained
   float m_bar;
};


It seems the current standard guarantees this only for POD types.

9.2.17

A pointer to a POD-struct object, suitably converted, points to its initial member (or if that member is a bit-field, then to the unit in which it resides) and vice versa. [Note: There might therefore be unnamed padding within a POD-struct object, but not at its beginning, as necessary to achieve appropriate alignment. ]

However, the C++0x standard seems to extend this guarantee to "standard-layout struct object"

A standard-layout class is a class that:

— has no non-static data members of type non-standard-layout class (or array of such types) or reference,

— has no virtual functions (10.3) and no virtual base classes (10.1),

— has the same access control (Clause 11) for all non-static data members,

— has no non-standard-layout base classes,

— either has no non-static data members in the most-derived class and at most one base class with non-static data members, or has no base classes with non-static data members, and

— has no base classes of the same type as the first non-static data member.

A standard-layout struct is a standard-layout class defined with the class-key struct or the class-key class.

It is probably likely that the assumption holds in practice (and the former didn't just have these distinctions, though this could have been the intention)?


It is not guaranteed for non-POD types. C++ Standard 9.2/12:

Nonstatic data members of a (non-union) class declared without an intervening access-specifier are allo- cated so that later members have higher addresses within a class object. The order of allocation of nonstatic data members separated by an access-specifier is unspecified (11.1). Implementation alignment require- ments might cause two adjacent members not to be allocated immediately after each other; so might requirements for space for managing virtual functions (10.3) and virtual base classes (10.1).

In your case you have non-POD type since it contains custom destructor. More about POD types you could read here.


The latest C++ spec draft says this is ok, as long as the class qualifies as a standard layout class, which just requires

  • has no non-static data members of type non-standard-layout class (or array of such types) or reference,
  • has no virtual functions (10.3) and no virtual base classes (10.1),
  • has the same access control (Clause 11) for all non-static data members,
  • has no non-standard-layout base classes,
  • either has no non-static data members in the most-derived class and at most one base class with non-static data members, or has no base classes with non-static data members, and
  • has no base classes of the same type as the first non-static data member.

Depending on the definition of MyContained, your class might or might not be standard layout

Note that POD-classes are the intersection of standard layout and trivially copyable classes

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号