是成员指针固定大小和重新解释
我试图创建一个模板类,其中包含一个指向任意类实例和函数的指针,如下所示:
template<class C>
class A {
typedef void (C::*FunctPtr)(); //e.g. void C::some_funct();
FunctPtr functPtr_;
C* instPtr_;
public:
A(FunctPtr functPtr, C* instPtr)
: functPtr_(functPtr)
, instPtr_(instPtr) {}
};
但是,我希望能够创建此类的实例,而无需使用放置新动态内存分配。 C ++标准是否保证这个模板类对于所有类C都是固定的大小?
在Don Clugston关于指针的文章中,我注意到各种编译器上的成员函数指针的各种大小的图表和一些编译器并不总是相同的大小。 我以为我被洗了,但这是符合标准吗? 从C ++标准秒开始。 5.2.10重新演绎演员:
- 将“指针成员函数”类型的prvalue转换为指向成员函数类型的不同指针并返回到其原始类型,从而产生指向成员值的原始指针。
C ++标准中的那条语句是否指示成员函数指针的大小相同?
如果不是,我想我仍然可以按照以下方式重写代码以明确利用reinterpret_cast保证:
class GenericClass;
template<class C>
class A {
typedef void (GenericClass::*GenFunctPtr)();
typedef void (C::*SpecificFunctPtr)();
GenFunctPtr functPtr_; //store any kind of function ptr in this fixed format
GenericClass* instPtr_;
public:
A(SpecificFunctPtr functPtr, C* instPtr)
: functPtr_(reinterpret_cast<GenFunctPtr>(functPtr))
, instPtr_(reinterpret_cast<GenericClass*>(instPtr)) {}
void DoSomething()
{
//now convert pointers back to the original type to use...
reinterpret_cast<SpecificFunctPtr>(functPtr_);
reinterpret_cast<C*>(instPtr_);
}
};
现在看起来要求所有的尺寸都一样,而且要符合标准,对吧? 我更喜欢第一个选项,但是如果我必须第二个选项也可以。 思考?
我不知道是否在标准中指定了成员指针的实现细节(找不到它),但由于我们知道C*
对于所有C
都具有相同的大小,所以我们可以确定它的大小FunctPtr
的各种类型C
,只需添加一个static_assert
:
template <class C>
class A {
typedef void (C::*FunctPtr)(); //e.g. void C::some_funct();
static_assert(sizeof(FunctPtr) == 16,
"unexpected FunctPtr size"); // from coliru, clang and gcc
FunctPtr functPtr_;
C* instPtr_;
...
};
至少我尝试过几种类型({base,derived,multiple derived} x {virtual,non-virtual}),它总是给出相同的大小。
这可能是特定于平台和/或编译器的,因为指向成员函数的指针非常奇怪:
仅使用单一继承的类的指向成员函数的大小只是指针的大小。
使用多重继承的类的指向成员函数的大小是指针的大小加上size_t的大小。
这不是我在clang或gcc中看到的。
Microsoft编译器使用不同大小的成员指针,具体取决于类的复杂程度。 从技术上讲,这不符合规范(因为即使在类定义不可见的情况下,您也可以定义指向成员的指针),但它在实践中运行得非常好,以至于默认情况下它会这样做。 编译器和编译器开关可用于控制此行为。 请参阅https://msdn.microsoft.com/en-us/library/83cch5a6.aspx。
即使如此,任何给定类的指针总是相同的大小,只是不同的类可能有不同大小的成员指针。
链接地址: http://www.djcxy.com/p/28757.html上一篇: are member pointers fixed in size and reinterpret
下一篇: c++