可能重複:
How does dereferencing of a function pointer happen?值的函數/ C++
如果我們有
void f() {
printf("called");
}
然後將以下代碼將導致 「calledcalled」 輸出:
f();
(*f)();
我真的不明白這是如何工作的... *f
和f
有什麼區別?你爲什麼要用後一種語法調用一個函數?
可能重複:
How does dereferencing of a function pointer happen?值的函數/ C++
如果我們有
void f() {
printf("called");
}
然後將以下代碼將導致 「calledcalled」 輸出:
f();
(*f)();
我真的不明白這是如何工作的... *f
和f
有什麼區別?你爲什麼要用後一種語法調用一個函數?
有兩種方法來調用一個函數在C++:
按名稱:
f();
通過函數指針:
typedef void (*fptr_t)();
fptr_t fptr = &f;
(*fptr)();
現在,使用地址運算符函數名稱(&f
)顯然會創建一個函數指針。但是,當滿足某些條件時,函數名可以隱式轉換爲函數指針。所以上面的代碼可以寫成:
typedef void (*fptr_t)();
fptr_t fptr = f; // no address-of operator, implicit conversion
(*fptr)();
你的第二個例子做的正是這一點,但使用臨時變量來保存函數指針,而不是一個名爲局部變量。
我更喜歡在創建函數指針時使用address-of,意思就更清晰了。
相關說明:如果提供函數指針,函數調用運算符將自動解引用函數指針。所以,這也是合法的。
typedef void (*fptr_t)();
fptr_t fptr = &f;
fptr();
這與模板非常有用,因爲相同的語法運作的,你是否有一個函數指針或仿函數(對象實施operator()
)傳入
而且沒有捷徑可與指向成員的指針,那裏你需要顯式地址和取消引用操作符。
在C,@Mehrdad explains that all function calls use a function pointer.
我希望我們會在C++ 0x中看到更加微妙的問題,包括lambda表達式和所有... – Mehrdad 2011-04-30 22:06:17
第一個是第二個語法糖。第二個很明顯,你是通過一個指針進行調用的,它主要用於函數指針而不是常規函數,以使這種區別更加明顯。
那麼第二個隱式地將指針指向'f',然後通過那個調用函數? – 2011-04-30 20:13:19
@Matti:不,第二個是* dereferencing *指針並調用函數,這是第一個*隱含*做的。 (*符號有幾個含義 - 除了乘法之外,它可以是解引用*運算符*和指針*聲明*。不要讓它們混淆。) – Mehrdad 2011-04-30 20:14:03
f是一個地址。 (* f)()是對該地址的函數調用。 – 2011-04-30 20:14:43
正如陣列型幾乎完全等同於相應指針到單元類型,一個功能類型是完全等同於相應指針到功能類型:
void (*func1)() = f; // function type -> pointer-to-function type
void (*func2)() = &f; // pointer-to-function type -> pointer-to-function type
並且還
void (*func)() = ...;
func(); // pointer-to-function type + function-call operator
(*func)(); // function type + function-call operator
所以,在
(*f)();
你提領f
(隱式轉換爲&f
),然後應用函數調用操作符。
這需要有兩個問題,一個關於C,一個對C++的,因爲他們有微妙的不同的規則(儘管最終相同的行爲)。 – 2011-04-30 20:49:58