如果我在清楚的情况下使用指针,编译器可以内联一个虚函数吗? [英] Can a compiler inline a virtual function if I use a pointer in a clear situation?

查看:185
本文介绍了如果我在清楚的情况下使用指针,编译器可以内联一个虚函数吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已阅读内联虚拟功能真的是非-sense?

他们说如果情况不明确,编译器应该内联虚函数

但是:


对象而不是对象的引用。

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

所以如果我有一个 B 类从 A (包含 virtual void doSth()函数) B * 指针,而不是 A *

So what if I have a B class derived from an A one (which contains a virtual void doSth() function) and I use the B* pointer, not the A*:

B* b = new B;

b->doSth();




  1. B 没有任何子类。这是相当明显的(在编译时)应该调用什么函数。所以可以内联。 c c > doSth()函数。因此编译器应该知道唯一的函数是 B :: doSth()。我想它不内联吗?

  1. Suppose that the B hasn't any child classes. It's rather obvious (on the compile time) what function should be called. So it's possible to be inlined. Is it in fact?
  2. Suppose that the B has some child classes but these classes haven't its own doSth() function. So compiler should "know" that the only function to call is B::doSth(). I guess it doesn't inline though?


推荐答案

c $ c> B 有任何派生类。在这种情况下, b 指向一个 B 对象,因此编译器可以内联调用。

It doesn't matter whether B has any derived classes. In that situation b points to a B object so the compiler can inline the call.

当然,任何可靠的现代编译器都可以,并会在你的情况下做到这一点。如果你不使用指针,它变得很容易。这不是一个真正的优化。事实上,你可以省略一个虚拟调用,然后变得明显只通过查看在 - 操作符左侧的AST节点。但是如果你使用指针,你需要跟踪pointee的动态类型。但现代编译器是有能力的。

And surely any decent modern compiler can and will do that in your situation. If you don't use pointers it becomes a whole lot easier. It's not really an "optimization" then. The fact that you can omit a virtual call then becomes obvious by only looking at the AST node at the left side of the .-operator. But if you use pointers, you need to track the dynamic type of the pointee. But modern compilers are capable of that.

编辑:有些实验是有序的。

Some experiment is in order.

// 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 0, i32 2) to i32 (...)**), i32 (...)*** %5, align 4
  %tmp = bitcast i8* %4 to %struct.B*
  tail call void @B::f()(%struct.B* %tmp)
  ret void
}
// ...

可以看出,clang直接调用 f a 指向 A 时,以及当它指向 B 。 GCC也这样做。

As can be seen, clang does direct calls to f, both when a points to a A and when it points to a B. GCC does that too.

这篇关于如果我在清楚的情况下使用指针,编译器可以内联一个虚函数吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆