關於inline的誤解

誤解:inline函數沒有單獨的函數體,也不能取地址。

inline修飾並不會改變函數的通常語義,仍可通過函數指針調用:

inline void f() {}

void g() {
  void (*p)() = f;
  p();
}


------------------------------------------------------------------------


誤解:inline一定導致代碼膨脹

class Foo {
public:
        int Bar() { return foo; }
private:
        int foo;
};

這樣的Foo::Bar inline會讓binary變小


------------------------------------------------------------------------


誤解: inline函數一定是internal linkage/no linkage的。

inline與函數的linkage無關。inline函數同樣可以用static和extern修飾,並具
備同一般函數相同的linkage。標準要求external linkage的inline函數在所有編
譯單元中具有相同的地址。external linkage的inline函數內定義的靜態變量同
樣應在所有編譯單元中表現爲單一對象,具有相同的地址。


------------------------------------------------------------------------


誤解: 如果inline函數包含循環/調用了其他函數/遞歸調用自己,編譯器就無法
      將其展開。

某些早期的編譯器有這類限制,但對現代編譯器來說它們不再是inline展開的障
礙了。

[insert RoachCock's example here]


------------------------------------------------------------------------


誤解:inline和virtual不能同時修飾一個函數。

inline和virtual並不衝突。以下程序編譯通過。

#include <iostream>

struct A
{
  inline virtual void f()
  {
    std::cout << "inline virtual" << std::endl;
  }
};


------------------------------------------------------------------------


誤解:virtual函數即使聲明爲inline,由於是late binding,無法判斷實際
      調用的版本,編譯器也無法展開。

虛函數調用並不總是late binding。

示例:

struct Base
{
  virtual void foo(){cout << "Base::foo" << endl;}
};

struct Derived : Base
{
  void foo(){cout << "Derived::foo" << endl;}
};

void bar(Base& b)
{
  b.foo();  // late binding. if b is a Derived, call Derived::foo
  b.Base::foo();  // early binding. inline
  Derived d;
  d.foo();  // early binding. inline
}

另外,儘管在您的編譯器中很可能還沒有實現,但即使late binding理論上也是
可以展開的。
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章