2012-10-31 58 views
2

以下例子。我創建一個名爲s的函數指針,將其設置爲f並調用它。編譯沒有問題,當然:函數指針語法歧義

void f() {} 

int main() { 

    void (*s)(); 

    s = f; 

    s(); 

} 

但藉此在下一個例子,在那裏我現在宣佈s爲「函數參考」(如果它所謂的),並設置爲f在線。這編譯也很好:

void f() {} 

int main() { 

    void (&s)() = f; 

    s(); 

} 

這兩種方法創建和初始化函數指針有什麼區別?請注意,當我使用參考語法時,我需要將它「in-line」初始化爲f,而使用「指針」語法,我有兩種方法可以完成。你能解釋一下嗎?那麼,你能解釋它們在可用性方面的差異嗎?何時我必須使用一種形式而不是其他形式?

回答

3

從根本上說,主叫方沒有明顯的區別。但是decl方肯定不會。正如你所指出的,參考文獻必須初始化爲。這使他們「更安全」,但即使如此也不能保證「安全」。

函數指針不需要指向某個函數。它可能是NULL,甚至可能是未初始化的(指向垃圾)。這並不重要,因爲你可以隨時改變它(你不能用引用來做)。

void (*s)(); // uninitialized 

void (*s)() = NULL; // set to null 

後來

void foo() 
{ 
} 

s = foo; 

你可以做那些沒有與基準的。參考必須被初始化爲東西和preferabley東西有效

void (&f)() = foo; // ok. also references foo(). 
void (&f)() = *s; // also ok, but wait, is s valid?? does it have to be?? 

然而,即使在這裏,函數引用是不能保證是安全的,只是安全。你當然可以這樣做:

void (*s)(); 
void (&f)() = *s; 

你可能會得到一個編譯器警告出這(我做的,「正在初始化之前使用的」),但最終f至今仍是一個「功能」的引用根本不是的功能;只是s指針中的隨機堆棧垃圾。更糟的是,因爲引用不能被重新分配。這東西會總是指向垃圾。

0

對類型P的引用很像類型P的const指針(不是指向const P的指針,它不同)。

如果你的類型P是一個函數類型,它們所發生的大部分差異並不重要。 &的行爲稍有不同,您可以直接將指針指定給非常量指針,並且採用一個指針的函數可能不會採用其他指針。

如果P型不是一個函數式將有其他的差異載荷 - 操作員=,臨時對象的壽命等

總之,答案是「沒有太大」。

2

與任何指針/參考的區別是相同的。

引用必須被初始化,並且不能在稍後重新分配:

int i,j; 
int &r = i; 
r = j; // i = j, not &r == &j 

參考文獻不能被視爲對象從它們所引用的對象不同的(相對於指針,這是對象從它們指向的對象是不同的) ...

int i; 
int *p = &i; // &p != &i 
int &r = i; // &r == &i 

使用函數指針看起來語法一樣使用參考,但那是因爲與函數指針一個特殊的規則,允許您使用它們,而不提領人。

2

你自己說過,與引用不同的是,必須在聲明時綁定它,這可以確保引用始終引用有效對象。 另一個區別是引用在聲明後不能重新綁定,所以它們在整個生命週期中都引用一個對象並且只引用一個對象。

除此之外它們是相同的東西。 我遇到過一些純粹主義者喜歡引用,並指出指針是C不應該使用的痕跡。 其他人更喜歡指針,因爲他們更明確地指出他們是指針。

是否使用一個或另一個取決於您的需求。選擇的方式是,儘可能使用引用,但如果您確實需要能夠將其指向不同的函數,請使用指針。

0
  1. 函數標識符是函數類型的表達式,但它們隱式轉換爲指針函數類型或函數引用類型。所以它們可以傳遞給參考或指針的構造函數,也可以傳遞給指針的operator =。

  2. 由於引用在語法上的行爲與實例相似,因此無法對引用而不是引用的對象進行操作。這就是爲什麼他們只能被初始化。順便說一下,C++中的首選語法是帶括號的,而不是=

  3. 您應該在可能的情況下使用引用,僅當您不能使用引用時才使用指針。原因在於,由於許多事情無法完成引用(指向NULL,更改引用的對象,刪除它等),讀取代碼時必須查找的內容更少。另外它還可以節省一些*&個字符。