在没有虚拟方法或超类的类中,是否可以安全地假设(第一个成员变量的地址)==这样? [英] In a class with no virtual methods or superclass, is it safe to assume (address of first member variable) == this?

查看:58
本文介绍了在没有虚拟方法或超类的类中,是否可以安全地假设(第一个成员变量的地址)==这样?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我制作了一个私有API,该API假定该类中第一个成员对象的地址将与该类的this-pointer相同...这样,该成员对象就可以轻松地得出该对象的指针。



鉴于我愿意确保容器类不会从任何超类继承,所以它是其中的一员。没有任何虚拟方法,执行此技巧的成员对象将是第一个声明的成员对象,该假设对任何C ++编译器都有效,还是我需要使用offsetof()运算符(或类似方法)保证正确性?



换句话说,下面的代码符合我在g ++下的预期,但是它可以在任何地方使用吗?

  class MyContainer 
{
public:
MyContainer(){}
〜MyContainer(){} //非-虚拟dtor

私人:
类MyContained
{
公共:
MyConta ined(){}
〜MyContained(){}

//假设声明包含对象的唯一位置是m_contained
//(如下所示),预期在任何C ++编译器上?
MyContainer * GetPointerToMyContainer()
{
return reinterpret_cast< MyContainer *>(this);
}
};

MyContained m_contained; //必须是MyContainer中声明的第一个成员项目
int m_foo; //其他成员项可以在m_contained
float m_bar之后声明;
};


解决方案

似乎当前标准仅对POD类型保证了这一点



9.2.17


指向POD结构对象的指针,经过适当转换的
指向其
的初始成员(如果该成员是
位域,则指向其所在的单元
),反之亦然。 [注意:
因此,在POD结构对象
中可能存在未命名的
填充,但在其开始处没有,为必要的对齐
。 ]


但是,C ++ 0x标准似乎将这种保证扩展到了标准布局结构对象


标准布局类是
的类,

-不具有
类型的非标准布局类(或此类类型的
数组)或引用的静态数据成员



-没有虚函数(10.3)和
没有虚拟基类(10.1),



-对所有非静态对象具有相同的访问控制(子句
11)数据成员



-没有非标准布局的基础
类,



在派生度最高的类别中没有非静态数据
成员,并且在最多一个具有非静态
数据成员的基类中没有
,或者没有具有非静态数据
的基类静态数据成员,并且



-没有与第一个非静态数据成员相同类型的基类



A stan dard-layout结构是一个
标准布局类,定义了
class-key结构或class-key
类。


该假设很可能在实践中成立(前者不仅具有这些区别,尽管这可能是故意的)?


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 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆