我看到网上,有很多所谓的,引用是引用变量,指针是指针变量,
对某个变量起了个别名之类的错误言论.
百度百科都是说引用是变量的别名,这是误人子弟!
以下是百度百科原文
引用(reference)就是C++对C语言的重要扩充。引用就是某一变量(目标)的一个别名,对引用的操作与对变量直接操作完全一样。引用的声明方法:类型标识符
&引用名=目标变量名;
如果想方便他人理解,这么说,还可以让他人认同.
但是言之凿凿的说引用和指针是两个类型,那么就太可笑了.
什么是引用?
引用其实不过是指针更方便的写法罢了.
不过又为了不让C++过于隐晦和繁琐,对其加上了限制,比如不允许二次引用.
可能有的人,觉得不信,因为可能上学的时候,就被老师教育,引用是个新变量类型,或者说,是变量别名.
但我想说的是,这些都是错误的!
那么如何证明这一点呢?
很简单,我们写一段代码就知道了.
void AddReferen(int&a, int&b)
{
a+=b;
}
void AddPointer(int*a,int*b)
{
*a+=*b;
}
这是两个函数,上面的是以引用作为参数,而下面的,则是以指针作为参数传递
大家可以明显的看到,哪有什么引用参数,在汇编层面上,都是以指针来传递的.
除了两个函数的地址以为,它们连一丝一毫的不同都没有.
在编译器看来,这就是两个一样的函数.
如果以release模式编译,大家可以大胆的猜一猜,我们还会有这两个函数了么?
很显然,只会剩下一个函数地址.
不过这么简单的函数,一般的编译器会直接替换掉.
现在我们重新写一段代码,这次我用VisualStudio来展示.
#include <iostream>
struct RefeAddress
{
int& reference; // 引用的地址会被编译器优化掉,而结构体必须存在地址,这是硬性规定,只有这样可以避免引用地址被优化.
RefeAddress(int varA) :reference(varA){}
};
int main(void)
{
int varA{ 1 };
RefeAddress ref{ varA };// 给引用初始化
std::cout << "变量A的地址:\t" << &varA << std::endl;
std::cout << "引用的地址:\t" << &ref.reference << std::endl;
std::cout << "Refe对象的地址:\t" << &ref << std::endl;
return 0;
}
引用存在自己的地址,因为是指针类型,所以在32程序是4字节.
只不过只有结构体硬性要求内存对其,所以在结构体里面声明的变量地址不会被优化掉.
记住一点,所有的局部变量都可以没有地址,这取决于编译器的决定
用32位的汇编代码,方便各位容易理解.
可以看到
006017A3 mov eax,dword ptr [ref]
006017A6 mov ecx,dword ptr [numberA]
006017A9 mov dword ptr [eax],ecx
006017AB mov eax,dword ptr [intP]
006017AE mov ecx,dword ptr [numberA]
006017B1 mov dword ptr [eax],ecx
和之前的函数一样,实现都是靠ptr来实现的.
这都证明了,引用就是指针.
既然引用就是指针,那么我们为什么需要要到引用呢?
很简单的道理.
因为这样写,很爽,可以让程序员的双手,减少离开a`z的主键区.
运用小帮助
如果你有一个函数,类似以下
int& Number(int &var)
{
return var;
}
你需要这个函数的返回值赋值给相同类型的指针.
只要在这个函数前加&取地址符,来进行变量升级操作即可
因为引用虽然也是指针,但是它会返回值,而不是地址.
#include <iostream>
int& Number(int &var)
{
return var;
}
int main(void)
{
auto var {Number(*new int { 0 })};
auto* intP {&Number(*new int{ 1 })};
std::cout << var << "|" << *intP << std::endl;
return 0;
}
如果你能明确的理解下面这行代码,那么证明你在内存层面的认知,是很不错的.
你已经可以灵活的去运用一级指针了
auto* intP {&Number(*new int{ 1 })};
我们先来分析&Number这个函数,Number函数的返回值类型是引用,所以它会返回地址中的值.
而指针可不认你地址中的值,它只认地址.
所以我们需要对这个值,进行升级操作,也就是取地址&,得到一级指针. 这样intP就可以被赋值了.
再来看分析*new int{1}这一段.
Number函数的参数1,是个int引用,所以它不认地址,只认值.
而new的返回值,则是个一级指针,所以我们需要用 * 来将其降级操作.
取地址中的值给它.
然后它再靠这个值,取地址,给自己.
听起来很绕,但在汇编代码中,这不会有任何的效率影响,大家都是只认地址的.
这一章就没有代码下载啦.
但是也可以去github上下载我其他的代码
https://github.com/Babaoxianyu/BlogSpotSource
配合博客上的文章,快乐理解C++的一些知识点.