我知道我可以傳遞一個函數指針作爲模板參數,並得到調用它內聯,但我想,如果這幾天內聯一個「明顯的」內聯能夠函數像任何編譯器:C++函數指針內聯
inline static void Print()
{
std::cout << "Hello\n";
}
....
void (*func)() = Print;
func();
在Visual Studio 2008下,它足夠聰明,可以直接調用指令,所以它似乎是一種恥辱,它不能再走一步嗎?
我知道我可以傳遞一個函數指針作爲模板參數,並得到調用它內聯,但我想,如果這幾天內聯一個「明顯的」內聯能夠函數像任何編譯器:C++函數指針內聯
inline static void Print()
{
std::cout << "Hello\n";
}
....
void (*func)() = Print;
func();
在Visual Studio 2008下,它足夠聰明,可以直接調用指令,所以它似乎是一種恥辱,它不能再走一步嗎?
GNU的G ++開始在優化級別-O1
main:
subq $8, %rsp
movl $6, %edx
movl $.LC0, %esi
movl $_ZSt4cout, %edi
call _ZSt16__ostream_insertIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_E
movl $0, %eax
addq $8, %rsp
ret
其中.LC0是.string 「你好\ N」 4.5內聯對我來說。
比較,沒有優化,G ++ -O0,它沒有內聯:GCC的
main:
pushq %rbp
movq %rsp, %rbp
subq $16, %rsp
movq $_ZL5Printv, -8(%rbp)
movq -8(%rbp), %rax
call *%rax
movl $0, %eax
leave
ret
偉大的這是很好的知道,因爲有各種有用的構造,這將使他們的使用零性能影響:) 一個恥辱,Visual C++不是很聰明! 謝謝。 – iam 2010-06-03 03:49:36
那麼編譯器並不真正知道該變量是否會被覆蓋到某處(可能在另一個線程中?),所以它在謹慎的方面發生了錯誤,並將其作爲函數調用來實現。
我剛剛在版本構建中檢查了VS2010,它沒有被內聯。
順便說一句,你裝飾功能inline
是沒用的。該標準說如果你得到一個函數的地址,任何inline
提示都將被忽略。
編輯:但請注意,雖然你的函數沒有被內聯,但變量IS不見了。在反彙編中,call
使用直接地址,它不會將該變量加載到寄存器中並調用該地址。
是的,這是什麼我以爲我只是試着__restrict,而且const也無濟於事。是的,我嘗試內聯和__forceinline,因爲你永遠不知道:) IE:void(* const __restrict func)()= Local :: Print; 我希望在VS2010中,他們可能會因爲lambda等原因而產生 - 是否__restrict改變了VS2010的局面? 謝謝 – iam 2010-06-02 16:37:55
不,編譯器拒絕內聯,這有點奇怪,因爲如果它消除了變量,那麼變量就沒有變化的危險,所以它可以用函數體來代替'call'。呵呵.. – Blindy 2010-06-02 16:43:03
編譯器不必假定變量可以在另一個線程中被覆蓋。如果有可能同一個線程可能會覆蓋變量,編譯器必須保證它的安全,但是在OP所示的簡單情況下,不存在這種風險(這也是爲什麼它能夠消除變量)。編譯器*應該*能夠內聯這樣一個簡單的例子。 – jalf 2010-06-02 18:06:57
新版本(4.4以上版本)有一個選項名爲-findirect,內聯。如果GCC能證明自己的函數指針是常量,那麼它會直接調用函數或完全內聯函數。
你確定這不是對'ostream <<'的直接調用指令嗎? – James 2010-06-02 16:19:56
請使用編輯器中的「101010」按鈕格式化您的代碼。 – sbi 2010-06-02 16:22:21
是的,我檢查了大會。在代碼格式我不知道,但現在我:) – iam 2010-06-02 16:38:44