指针或引用(有人称之为别名)。编译器真的在意吗?
让我们做一个简单的实验,我相信这能帮助任何想理解指针和引用的人。
让我们声明两种简单的函数版本
但暂时我们只使用 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;};
|
而使用指针调用引用的调用将被更改为
使用指针的调用。
你可以尝试注释掉代码,用两种方式调用函数,看看它们是如何工作的。
嗯,我希望这对某人有所帮助,或者至少让他们觉得有趣。