在没有虚拟方法或超类的类中,是否可以安全地假设(第一个成员变量的地址)==这样? [英] In a class with no virtual methods or superclass, is it safe to assume (address of first member variable) == this?
问题描述
我制作了一个私有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屋!