只是想问一下C规范/标准,
这与Qt无关,但一些Qt知识是被认可的;
C规范/标准是否允许两个方法具有相同的指针,我的意思是,如果编译器的优化检测到方法是二进制相同的,编译器是否允许为两个方法发出一次二进制?
示例:
class MyClassA {
inline void maybeOptimize1() {
// Some code.
}
};
class MyClassB : public MyClassA {
inline void maybeOptimize2() {
// Imagine exact same code as `maybeOptimize1()` here.
}
};
static_assert(&MyClassB::maybeOptimize2 != &MyClassA::maybeOptimize1);
字符串
重要性:
例如,在Qt框架中,我们有QMetaObject::IndexOfMethod
,如果传递给static_metacall(...)
,可以根据方法的指针来查找方法/slot的索引。
1条答案
按热度按时间1qczuiv01#
在C标准中没有非静态成员函数地址的概念。不可能获得这种函数的地址(在编译代码中的指令/符号地址的意义上)。
然而,指向成员的指针确实存在,并且如果两个函数都是非虚的并且给出了继承关系,则
static_assert(&MyClassB::maybeOptimize2 != &MyClassA::maybeOptimize1);
保证成功。(否则,比较的结果是未指定的,这在static_assert
的显式常量求值上下文中意味着程序将是病态的。)参见[expr.eq]/4。如何实现这一点取决于编译器。例如,在Itanium C ABI中,对于非虚非静态成员函数,函数指针与对象指针调整一起存储,并且我认为消除重复的函数通常不会允许区分指针,因为基类对象偏移量为零,所以这是不允许的优化。(至少假设类有外部链接。否则我可以看到编译器静态地推理哪些地址被占用。)如果偏移量不为零,所以对象指针调整不同。我需要更详细地考虑这个问题。
据我所知,MSVC的成员指针实现不符合标准,所以我不能告诉它将如何表现。
然而,编译器足够聪明,例如,将具有相同主体的函数之一简化为跳转到另一个函数,以便保存重复指令。这仍然为发出的函数提供唯一的符号地址。
关于
QMetaObject::IndexOfMethod
,我不能说什么,不管它是否依赖于成员指针,使用特定于编译器的非标准方法,或者它是否依赖于技术上UB的hack,因此在规范之外(这并不罕见)。