指向C++中数据成员的指针的值

the value of pointer to data member in C++

本文关键字:指针 数据成员 C++ 指向      更新时间:2023-10-16

遇到一个非常奇怪的问题,有人知道这是什么原因吗?该代码在Visual Studio 2012下进行了测试。

#include <iostream>
struct A {
  int a;
};
struct B {
  int b;
};
struct C : public A, public B {
  int c;
};
int main() {
  int C::*p = &C::b;
  std::printf("%pn", &C::b); //00000000
  std::printf("%pn", p);     //00000004
  return 0;
}

指向成员的指针不仅仅是普通的C指针,因此将它们传递给printf实际上是未定义的行为,因为printf将相信"%p",并将指向成员的指示器C型转换为void*

第4.11段列出了标准允许的指向成员的指针的唯一转换:

  1. Null指针常量可以转换为Null成员指针值
  2. 如果B是D的可访问、非歧义和非虚拟基类,则B::*T可以转换为D::*T

指向成员的指针实际上可以有不同的大小,这取决于它们指向的类。

有关MSVC中指向成员实现的指针的更多信息,请参阅此处:http://blogs.msdn.com/b/oldnewthing/archive/2004/02/09/70002.aspx

注意可能出现的意外结果

printf("typeid(&C::b) = %sn",typeid(&C::b).name());
printf("typeid(&B::b) = %sn",typeid(&B::b).name());

VS2010收益率:

typeid(&C::b) = int B::*
typeid(&B::b) = int B::*

这表明&C: :b是类型b上的成员指针。由于C是从b派生的,指针可以自由转换为类型C上的成员指示器。这解释了您看到的两个值之间的差异&C: :b是类型b上的成员函数指针,int C::*p是类型C上的成员功能指针。

int B::*p_b = &B::b;
int C::*p_c = p_b;
printf("p_b = %pn", p_b);
printf("p_c = %pn", p_c);