微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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……….

原文地址:https://www.jb51.cc/c/116625.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐