简体   繁体   English

C ++ - 当无法进行函数内联时?

[英]C++ - When function inlining is not possible?

Folks, 伙计们,

I was reading " Thinking in C++" (Chap - Inline functions), where I encountered this statement. 我正在阅读“ 用C ++思考” (Chap - Inline函数),在那里我遇到了这个语句。

"The compiler also cannot perform inlining if the address of the function is taken implicitly or explicitly". “如果隐式或明确地采用函数的地址,编译器也无法执行内联”。

What does that mean by " taking address of function implicitly or explicitly " ? 这意味着“ taking address of function implicitly or explicitly ”是什么意思?
Why it is not possible to inline in this case ? 为什么在这种情况下无法内联?

Thanks. 谢谢。

Taking the address of a function means assigning it to a function pointer . 获取函数的地址意味着将其分配给函数指针 This can happen explicitly, as in the linked examples. 这可以明确地发生,如在链接的示例中那样。 I am not sure what the author means by "implicitly" - maybe things like passing a function as a parameter to another function. 我不确定作者的意思是“暗中” - 也许是将函数作为参数传递给另一个函数。

If the address of the function is taken, it must have an address in the first place. 如果采用该函数的地址,则它必须首先具有地址。 Since inlining means basically substituting calls to the function with a copy of its body, after such a transformation the function no more exists, thus has no address - only n distinct copies of identical code in places where there used to be calls to that function. 由于内联意味着基本上用对其主体的副本替换对函数的调用,在这样的转换之后该函数不再存在,因此没有地址 - 在过去曾经调用该函数的地方只有n个相同代码的不同副本。 Thus if a function's address is used in any way, it can't be inlined. 因此,如果以任何方式使用函数的地址,则无法内联。

Actually, the quote may mislead. 实际上,引用可能会误导。

If a function address is taken, then it is necessary to generate the function in the library/executable, because the execution of a function by its address consist in jumping the instruction pointer to the block of code describing the function. 如果采用函数地址,则必须在库/可执行文件中生成函数,因为通过其地址执行函数包括将指令指针跳转到描述函数的代码块。

However, it certainly does not prevent the compiler to inline the function in other places, when called directly. 但是,当直接调用时,它肯定不会阻止编译器在其他地方内联函数。

First, a review: 首先,审查:

// Explicit:
void foo();

void (*func_ptr)() = foo;


// Implicit
struct Foo { virtual void bar() {} }; // address used in V-Table

Second, inlining examples: 二,内联示例:

int main() {
  (*func_ptr)(); // probably not inlined as the compiler can difficultly assert
                 // that nobody may modified it... since it's non-const.

  foo(); // might be inlined

  Foo f;
  f.bar(); // might be inlined (the exact type of `f` is known)
           // this is called, "devirtualizing"

  Foo& g = accessSomeFoo();
  g.bar(); // probably not inlined unless the compiler can assert
           // the type returned by accessSomeFoo
           // (which requires knowing its definition)
}

I'm not sure if that is entirely true. 我不确定这是否完全正确。 However, if you take the address of a function, that function needs to exist in memory complete with the function's preamble and cleanup code. 但是,如果你获取一个函数的地址,那么该函数需要存在于内存中,并附带函数的前同步码和清理代码。 It's this preamble and cleanup that's omitted when inlining. 在内联时省略了这个序言和清理。 And you get a whole load of optimisation possibilites when inlined. 内联时,您可以获得大量优化可能性。

But a modern compiler should still be able to inline the function wherever it's possible to inline it. 但是现代编译器应该仍然能够在可以内联它的任何地方内联函数。 Consider: 考虑:

int compare (int a, int b)
{
  return a compared to b
}

int main ()
{
  a = array of ints

  qsort (a, compare); // take address of compare function, thus compare function exists in
                      // app as a proper function

  compare (value1, value2); // there's no reason why this can't be inlined
}

I think the quote should be more explicit about what can't be inlined: 我认为引用应该更明确无法内联的内容:

A function that is called via a function pointer can not be inlined. 通过函数指针调用的函数不能内联。

This is because there is no way to determine at compile time what function to inline at the point of the indirect call (the call via the function pointer). 这是因为没有办法在编译时确定在间接调用点(通过函数指针调用)内联的内联函数。 This doesn't mean to say that the function that has been pointed to by a function pointer can't be inlined wherever it is called directly. 这并不意味着函数指针指向的函数不能在任何直接调用的地方内联。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM