指向不完整类型的成员函数的指针

时间:2015-06-18 18:43:31

标签: c++ incomplete-type pointer-to-member

我不明白为什么为类添加前向声明会将其指针的大小更改为成员类型

#include <iostream>
using namespace std;

int main()
{
    //struct CL;
    //cout<<sizeof(int (CL::*)())<<endl; 
    struct CL{};
    cout<<sizeof(int (CL::*)())<<endl;
}

输出VS2013:
4

但如果我取消注释main()中的前两行,则输出不同:
16个
16

因此,在struct CL的定义之前只添加一个前向声明只会增加指向CL成员的指针的大小。为什么?我知道成员函数指针的大小取决于类型的结构(例如虚函数和基类可能会增加它),但为什么sizeof运算符可以应用于指向不完整类型成员的指针?或者它不能?我没有在标准中找到它

1 个答案:

答案 0 :(得分:8)

MSVC编译器使用不同大小的指针来指向成员函数作为优化。此优化违反了标准。感谢Igor Tandetnika MSDN form post中提到reinterpret_cast,[expr.reinterpret.cast] p10

  

类型为“指向X T1成员的指针”的prvalue可以是   显式转换为不同类型的prvalue“指向   如果YT2都是函数类型,则T1类型为T2的成员   或两种对象类型。 null成员指针值转换为   目标类型的null成员指针值。的结果   此转换未指定,但以下情况除外:

     
      
  • 将“指向成员函数的指针”类型的prvalue转换为指向成员函数类型的不同指针并返回其原始值   type产生指向成员值的原始指针。
  •   

因此有一个往返保证,这有效地迫使符合要求的实现对所有指向成员函数类型的指针使用相同的大小。

如果设置了/vmb switch,则执行MSVC优化。对于单继承的情况,优化的指向成员函数的指针只需要void*大小的存储,请参阅The Old New Thing: Pointers to member functions are very strange animals

如果你只是向前声明类型CL然后形成一个指向成员的函数,那么优化有望被取消(遗憾的是我找不到任何文档)。否则,在CL的定义之前和之后,您可能会得到不一致的大小。

顺便说一句,如果你在没有指定基础类型的情况下向前声明它们并且稍后明确定义枚举定义的基础类型,那么VS2010中的枚举可以得到不一致的大小。这仅适用于激活语言扩展名。