指向数据成员地址的指针 [英] Pointer to data member address

查看:93
本文介绍了指向数据成员地址的指针的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经阅读(在C ++对象模型内部),C ++中指向数据成员的指针的地址是数据成员的偏移量加1?
我正在VC ++ 2005上尝试此操作,但是我没有获得确切的偏移值.
例如:

Class X{  
  public:  
    int a;  
    int b;  
    int c;
}

void x(){  
  printf("Offsets of a=%d, b=%d, c=%d",&X::a,&X::b,&X::c);
}  

应打印a = 1,b = 5,c = 9的偏移量.但是在VC ++ 2005中,结果是a = 0,b = 4,c = 8.
我无法理解这种行为.
摘录:

然而,这种期望却落空了-这是一种传统的错误 适用于C和C ++程序员.

类中三个坐标成员的物理偏移量 如果vptr位于以下位置,则布局分别为0、4和8 如果将vptr放在末尾,则末尾为4、8和12 班级.从成员地址获取的值,但是, 总是被1撞到.因此实际值为1、5和9,并且 很快.问题是区分没有数据的指针 成员和指向第一个数据成员的指针.考虑例如:

float Point3d::*p1 = 0;   
float Point3d::*p2 = &Point3d::x;   

// oops: how to distinguish?   
if ( p1 == p2 ) {   
   cout << " p1 & p2 contain the same value — ";   
   cout << " they must address the same member!" << endl;   
}

为区分p1和p2,每个实际成员偏移值是 碰到1.因此,编译器(和用户)都必须记住 在实际使用该值寻址成员之前将其减去1."

解决方案

某物的偏移量是从开始算起的单位数.首先是开始,因此其偏移量为零.

请考虑一下您的结构位于内存位置100:

100: class X { int a;
104:           int b;
108:           int c;

如您所见,a的地址与整个结构的地址相同,因此它的偏移量(必须添加到结构地址中才能获得物料地址)为0.

请注意,ISO标准没有指定项目在内存中的放置位置.填充字节以创建正确的对齐肯定是可能的.在一个假设的环境中,int仅是两个字节,但它们所需的对齐方式是256个字节,因此它们不是0、2和4,而是0、256和512.


而且,如果您要摘录的那本书真的是Inside the C++ Object Model,那它的牙齿就有点长了.

它来自96年,并讨论了C ++内部的事实(对知道vptr在哪里有多好的讽刺意味,却错过了在错误的抽象层上工作的全部要点,永远不要在意).实际上,引言甚至指出解释了面向对象功能的基本实现 ..."(斜体字).

事实上,没有人能在ISO标准中找到任何要求这种行为的事实,再加上MSVC都不以这种方式行事的事实,使我相信,即使在远距离的某个特定实现中也是如此过去,这不是全部(或者必须是真实的).

作者显然领导了cfront 2.1和3团队,尽管这本书似乎具有历史意义,但我认为它与现代C ++语言(和实现)无关,至少我已经读过那些. /p>

I have read (Inside C++ object model) that address of pointer to data member in C++ is the offset of data member plus 1?
I am trying this on VC++ 2005 but i am not getting exact offset values.
For example:

Class X{  
  public:  
    int a;  
    int b;  
    int c;
}

void x(){  
  printf("Offsets of a=%d, b=%d, c=%d",&X::a,&X::b,&X::c);
}  

Should print Offsets of a=1, b=5, c=9. But in VC++ 2005 it is coming out to be a=0,b=4,c=8.
I am not able to understand this behavior.
Excerpt from book:

"That expectation, however, is off by one—a somewhat traditional error for both C and C++ programmers.

The physical offset of the three coordinate members within the class layout are, respectively, either 0, 4, and 8 if the vptr is placed at the end or 4, 8, and 12 if the vptr is placed at the start of the class. The value returned from taking the member's address, however, is always bumped up by 1. Thus the actual values are 1, 5, and 9, and so on. The problem is distinguishing between a pointer to no data member and a pointer to the first data member. Consider for example:

float Point3d::*p1 = 0;   
float Point3d::*p2 = &Point3d::x;   

// oops: how to distinguish?   
if ( p1 == p2 ) {   
   cout << " p1 & p2 contain the same value — ";   
   cout << " they must address the same member!" << endl;   
}

To distinguish between p1 and p2, each actual member offset value is bumped up by 1. Hence, both the compiler (and the user) must remember to subtract 1 before actually using the value to address a member."

解决方案

The offset of something is how many units it is from the start. The first thing is at the start so its offset is zero.

Think in terms of your structure being at memory location 100:

100: class X { int a;
104:           int b;
108:           int c;

As you can see, the address of a is the same as the address of the entire structure, so its offset (what you have to add to the structure address to get the item address) is 0.

Note that the ISO standard doesn't specify where the items are laid out in memory. Padding bytes to create correct alignment are certainly possible. In a hypothetical environment where ints were only two bytes but their required alignment was 256 bytes, they wouldn't be at 0, 2 and 4 but rather at 0, 256 and 512.


And, if that book you're taking the excerpt from is really Inside the C++ Object Model, it's getting a little long in the tooth.

The fact that it's from '96 and discusses the internals underneath C++ (waxing lyrical about how good it is to know where the vptr is, missing the whole point that that's working at the wrong abstraction level and you should never care) dates it quite a bit. In fact, the introduction even states "Explains the basic implementation of the object-oriented features ..." (my italics).

And the fact that nobody can find anything in the ISO standard saying this behaviour is required, along the fact that neither MSVC not gcc act that way, leads me to believe that, even if this was true of one particular implementation far in the past, it's not true (or required to be true) of all.

The author apparently led the cfront 2.1 and 3 teams and, while this books seems of historical interest, I don't think it's relevant to the modern C++ language (and implementation), at least those bits I've read.

这篇关于指向数据成员地址的指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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