c – 如果我在清楚的情况下使用指针,编译器可以内联虚函数吗?

我已经读了 Are inline virtual functions really a non-sense?.但我还是有一些疑问,没有发现任何答案.

他们说如果情况不模糊,编译器应该在虚拟函数内联.

然而:

This can happen only when the compiler has an actual object rather than a pointer or reference to an object.

那么如果我有一个派生自A的B类(它包含一个虚拟的void doSth()函数),而我使用B *指针,而不是A *:

B* b = new B;

b->doSth();

>假设B没有任何子类.这是很明显的(在编译时)应该调用什么函数.所以有可能内联.是吗?
>假设B有一些子类,但是这些类没有自己的doSth()函数.所以编译器应该“知道”调用唯一的函数是B :: doSth().我想这不是内联吗?

解决方法

B是否有任何派生类没有关系.在这种情况下,b指向B对象,因此编译器可以内联调用.

任何体面的现代编译器肯定会在你的情况下做到这一点.如果你不使用指针,它会变得容易一些.那不是一个真正的“优化”.通过查看运算符左侧的AST节点,可以省略虚拟呼叫的事实变得很明显.但是,如果使用指针,则需要跟踪被指针的动态类型.但是现代编译器是有能力的.

编辑:一些实验是有序的.

// main1.cpp
struct A {
  virtual void f();
};

struct B : A { 
  virtual void f();
};

void g() {
  A *a = new A;
  a->f();

  a = new B;
  a->f();
}

// clang -O2 -S -emit-llvm -o - main1.cpp | c++filt
// ...
define void @g()() {
  %1 = tail call noalias i8* @operator new(unsigned int)(i32 4)
  %2 = bitcast i8* %1 to %struct.A*
  %3 = bitcast i8* %1 to i32 (...)***
  store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*]* @vtable for A,i32 0,i32 2) to i32 (...)**),i32 (...)*** %3,align 4
  tail call void @A::f()(%struct.A* %2)
  %4 = tail call noalias i8* @operator new(unsigned int)(i32 4)
  %5 = bitcast i8* %4 to i32 (...)***
  store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*]* @vtable for B,i32 (...)*** %5,align 4
  %tmp = bitcast i8* %4 to %struct.B*
  tail call void @B::f()(%struct.B* %tmp)
  ret void
}
// ...

可以看出,cl ang ang ang……when when when when when……….

相关文章

本程序的编译和运行环境如下(如果有运行方面的问题欢迎在评...
水了一学期的院选修,万万没想到期末考试还有比较硬核的编程...
补充一下,先前文章末尾给出的下载链接的完整代码含有部分C&...
思路如标题所说采用模N取余法,难点是这个除法过程如何实现。...
本篇博客有更新!!!更新后效果图如下: 文章末尾的完整代码...
刚开始学习模块化程序设计时,估计大家都被形参和实参搞迷糊...