发布者:
2012年10月21日 (最后更新: 2012年10月22日)

指针和引用

评分: 3.1/5 (236 票)
*****
指针或引用(有人称之为别名)。编译器真的在意吗?

让我们做一个简单的实验,我相信这能帮助任何想理解指针和引用的人。

让我们声明两种简单的函数版本
但暂时我们只使用 int& 版本。

1
2
      //void some_function(int* i){cout << "\nvalue is " << *i << endl;};
      void some_function(int& i){cout << "\nvalue is " << i << endl;};


区别在于一个接受整数的引用,而另一个
接受指针。到目前为止一切都很简单,现在让我们调用函数使用
指针。

初始化变量。这只是为了让我们之后需要重新转换 fp
,我的意思是它除了在这里的例子之外没有其他意义。
所以现在 fp 是一个指向某个字节的指针。它不知道自己指向
一个函数了。
1
2
      char* fp = reinterpret_cast<char*>(&some_function);
      int ii = 5;


第一次调用 some_function,重新转换 fp
1
2
      
      reinterpret_cast<void(*)(int&)>(fp)(ii);

这将输出 ii 中的值,即 5。

所以没问题,一切都很简单。

第二次调用 some_function
现在让我们稍微改动一下来调用它
1
2
  
    reinterpret_cast<void(*)(int*)>(fp)(&ii);


这当然会输出相同的 5,因为它调用
的是同一个函数。但请注意,我使用了 int* 来转换指针
而不是 int&,而我们正在使用的函数声明是
int& 版本。

在第一次调用中,我们使用了正确的类型进行转换,而且我们不用
通过 &ii 来调用。在第二种情况下,因为我们使用了 int* 来转换
,我们需要通过 &ii 来调用,将其转换为一个 POINTER。

我认为这个简单的例子表明,当编译器看到一个引用,并且有人用不同的签名调用它,比如
int*,因为它那时已经将 int& 改为了到处都是 int*,所以它并不太在意。

换句话说,就编译器而言,它只看到
 
void some_function(int* i){cout << "\nvalue is " << *i << endl;};

即使你写成
 
void some_function(int& i){cout << "\nvalue is " << i << endl;};


而使用指针调用引用的调用将被更改为
使用指针的调用。

你可以尝试注释掉代码,用两种方式调用函数,看看它们是如何工作的。

嗯,我希望这对某人有所帮助,或者至少让他们觉得有趣。