有效的成员指针可以与 NULL 指针具有相同的值吗?
根据 ABI,
指向数据成员的指针是相对于数据成员基地址的偏移量 包含它的类对象... NULL 指针表示为 -1
但是,根据 c++ 标准(我有修订版 4296,它位于 4.11/1 中),
该类型的空成员指针值...是可区分的 从任何指向不是从空指针常量创建的成员的指针
,-1 可以是有效的偏移量。
考虑这种情况:
#include <iostream>
using namespace std;
struct A {
char a,b,c,d,e,f,g,h;
};
struct B {
int i;
};
struct C : A,B {};
int main() {
char C::*p=&C::h;
char B::*q = static_cast<char B::*>(p);
cout<< (q==nullptr) <<endl; //prints 1
}
在这段代码中,我的编译器(x86_64-linux-gnu 上的 g++4.9.2)将 h
放置在 A
的最后一个字节,并将B
位于 C
中的 A
之后。因此,C::A::h
相对于 C::B
基地址的偏移量为 -1。
(转换是合法的,其结果可以用在动态类型 C 的对象上,即使其静态类型是 B。标准说(5.2.9/12)“尽管 B 类需要不包含原始成员,通过指向成员的指针执行间接操作的对象的动态类型必须包含原始成员”)
我有什么误解?
(我怀疑我的误解是关于短语“包含原始成员的类”(5.2.9/12) - 考虑到 C::h
,该短语可能指的是到 A
而不是 C
,但标准明确指出 (10/2)“基类的成员也被视为成员派生类的”)
According to ABI,
A pointer to data member is an offset from the base address of the
class object containing it... A NULL pointer is represented as -1
However, according to the c++ standard (I have revision 4296, and there it's in 4.11/1),
the null member pointer value of that type ... is distinguishable
from any pointer to member not created from a null pointer constant
and -1 can be a valid offset.
Consider this situation:
#include <iostream>
using namespace std;
struct A {
char a,b,c,d,e,f,g,h;
};
struct B {
int i;
};
struct C : A,B {};
int main() {
char C::*p=&C::h;
char B::*q = static_cast<char B::*>(p);
cout<< (q==nullptr) <<endl; //prints 1
}
In this code, my compiler (g++4.9.2 on x86_64-linux-gnu), places h
at the last byte of A
, and places B
right after A
in C
. Hence, the offset of C::A::h
from the base address of C::B
is -1.
(The conversion is legal, and its result can be used on an object of dynamic type C, even if its static type is B. The standard says (5.2.9/12) "although class B need not contain the original member, the dynamic type of the object with which indirection through the pointer to member is performed must contain the original member")
What am I misunderstanding?
(I suspect that my misunderstanding is about the phrase "the class containing the original member" (5.2.9/12) - considering C::h
, that phrase may refer to A
and not to C
, but the standard explicitly says (10/2) "members of a base class are also considered to be members of the derived class")
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
[expr.static.cast]/p12:
“包含原始成员的类”是
a
。b
不是a
的基础或派生类,因此该行为不确定。[expr.static.cast]/p12:
The "class containing the original member" is
A
.B
is not a base or derived class ofA
, so the behavior is undefined.你错了,从基地址偏移-1是不可能的。对象的基地址是完整对象的地址,而不是该完整对象内的子对象的地址。
You're wrong, an offset of -1 from the base address is impossible. The base address of an object is the address of the full object, and not that off a subobject within that full object.