2012-10-31 139 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,更改引用的对象,删除它等),读取代码时必须查找的内容更少。另外它还可以节省一些*&个字符。