作者littleshan (我要加入劍道社!)
看板C_and_CPP
標題Re: [問題] inline 的內部運作疑惑
時間Wed Oct 26 00:09:18 2011
※ 引述《purpose (purpose)》之銘言:
: 那這邊 javac Myin.java 有點像 cl.exe src1.cpp 的狀況,其函數 foo 的定義
: 是在另外一個原始碼檔案,那 JAVA 又怎麼有辦法判斷 foo 不應該用函數調用的方式
: 而應該用 inline 的方式去執行來節省函數調用的時間呢?
: 無知的問題,請各位見諒...
以下的說明是某種 compiler 的實作方法
我不太確定目前的 java compiler 是否這樣做,但我認為理論上可行。
在編譯 Myin.java 的時候,compiler 看到這一行:
Myout.foo();
它不知道 Myout 的內容是什麼,於是它依照 class 的名稱,打開了同名的 Myout.java,
然後試圖了解 Myout 這個 class 的內容,知道 foo 是一個 static member function。
同時間,因為 java 是個界面與實作寫在一起的語言,compiler 不僅知道 foo 是 function,
還
一併看到了 foo 的內容。因此 compiler 可以在此做個評估:
foo() 的內容很簡單,我又知道其定義,所以可以進行 inline。
因此 compiler 輕鬆地做個展開:
Myout.foo(); → System.out.println("Myout.foo is called.");
* * * * *
我再把另一個 C++ 之所以需要 inline 的原因講清楚一點。
當我們為了達成 inline 而把某個函式的定義寫進 .h 的時候:
// foo.h
#ifndef FOO_H
#define FOO_H
#include <iostream>
void foo() // 一定要把定義寫出來,不然呼叫端無法展開
{
std::cout << "foo is called" << std::endl;
}
#endif
// caller_1.cpp
#include "foo.h"
void caller_1()
{
foo(); // 有看到 foo() 的定義,可以展開
}
// caller_2.cpp
#include "foo.h"
void caller_2()
{
foo(); // 也有看到 foo() 的定義,可以展開
}
然而,C++ compiler 處理 .h 的做法,是透過 preprocessor 來個「照單全收」,
因此使用 inline function 就會遇到兩難問題:
1. 如果 .h 中沒有寫出 foo 的定義,那麼呼叫端就無法展開。
2. 如果 .h 中寫出 foo 的定義,因為定義內容會被 preprocessor 加進所有編譯單元中,
因此 linker 會發現 foo 這個函式重覆定義。
為了解決這個問題,就必需用 inline 這個關鍵字去標示 inline function,
使得 compiler 在遇到 inline function 時會對該符號進行特別處理,
確保 linker 不會產生重覆定義的錯誤。
那為什麼 java 沒有相同的問題?
java compiler 在編譯 Myin.java 的時候,雖然會去「參考」Myout.java 的內容,
但它並不會像 C++ 的 preprocessor 那樣,把 Myout.java 的內容原封不動地搬進
Myin.java 然後一起來個大鍋煮,自然也不會有重覆定義的錯誤。
所以這個故事告訴我們:compiler 應該自行具備參考其它原始檔的能力,而不應該
透過 preprocessor。而 inline 這個字眼竟然能夠和 preprocessor 扯上關係,
可見 C++ 真的是個非常有趣的語言 XD
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 118.168.82.242
→ littleshan:我應該拿 D language 當作例子的... 10/26 00:12
→ diabloevagto:c++真的是...想出標準的人不知道是不是火星人.. 10/26 00:14
推 tropical72:推 :) 感謝解釋。 10/26 00:16
推 purpose:原來如此,關鍵的點是開啟別的原始碼,受教了 10/26 00:23
→ poyenc:執行前會先載入呀, 動手腳機會很多 10/26 00:27
→ angleevil:To diabloevagto.c++其實是個很嚴謹的語言.只是太多黑暗 10/26 08:46
→ angleevil:和灰色地帶了.所以有些規定是為了大原則去做 10/26 08:47