2

伙计们,

我正在阅读“用 C++ 思考”(Chap - 内联函数),在那里我遇到了这个语句。

“如果函数的地址被隐式或显式获取,编译器也无法执行内联”。

"" 是什么意思taking address of function implicitly or explicitly
为什么在这种情况下不能内联?

谢谢。

4

3 回答 3

5

获取函数的地址意味着将其分配给函数指针。这可以显式发生,如链接示例中所示。我不确定作者所说的“隐式”是什么意思——也许是把一个函数作为参数传递给另一个函数。

如果函数的地址被占用,它必须首先有一个地址。由于内联基本上意味着用函数体的副本替换对函数的调用,因此在这种转换之后,函数不再存在,因此没有地址——在曾经调用该函数的地方只有n 个相同代码的不同副本。因此,如果一个函数的地址以任何方式被使用,它就不能被内联。

于 2011-08-26T14:22:16.090 回答
4

实际上,报价可能会产生误导。

如果采用函数地址,则必须在库/可执行文件中生成该函数,因为通过其地址执行函数在于将指令指针跳转到描述该函数的代码块。

但是,当直接调用时,它当然不会阻止编译器在其他地方内联函数。

首先,回顾:

// Explicit:
void foo();

void (*func_ptr)() = foo;


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

二、内联示例:

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)
}
于 2011-08-26T14:43:37.637 回答
1

我不确定这是否完全正确。但是,如果您获取函数的地址,则该函数需要存在于内存中,并带有函数的前导码和清理代码。内联时省略了这个序言和清理。内联时,您会获得大量优化可能性。

但是现代编译器应该仍然能够内联函数,只要有可能内联它。考虑:

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
}

我认为引用应该更明确地说明不能内联的内容:

通过函数指针调用的函数不能被内联。

这是因为在编译时无法确定在间接调用(通过函数指针的调用)处内联哪个函数。这并不是说函数指针指向的函数不能在任何直接调用的地方内联。

于 2011-08-26T14:29:35.823 回答