C++教程-C++引用vs指针

C++引用vs指针
看起来相似,但它们之间存在一些区别。引用是一个变量,是对已存在变量的另一个名称,而指针是一个变量,存储另一个变量的内存地址。
引用是什么?
引用是一个变量,是对已存在变量的另一个名称。引用变量通过存储另一个变量的地址来创建。
引用变量可以被视为具有自动间接性的常量指针。这里,自动间接性指的是编译器会自动应用间接操作符(*)。
引用的示例:
int &a = i;
在上面的声明中,'a'是'i'变量的别名。我们也可以通过使用'a'变量来引用'i'变量。
让我们通过一个例子来理解。
#include <iostream>
using namespace std;
int main()
{
int i=8; // 变量初始化
int &a=i; // 创建一个引用变量
cout<<"变量 'i' 的值为:" << a;
return 0;
}
在上面的代码中,我们创建了一个引用变量'a',它是'i'变量的别名。创建引用变量后,我们可以通过'a'变量访问'i'的值。
指针是什么?
指针是一个变量,它存储另一个变量的内存地址。可以使用(*)操作符解引用指针来访问指针指向的内存位置。
引用和指针之间的区别
引用和指针之间的区别如下:
- 定义
引用变量是对已存在变量的另一个名称。它主要用于'按引用传递',其中将引用变量作为参数传递给函数,并且接收该变量的函数使用的是原始变量的副本。
让我们通过一个简单的例子来理解。
#include <iostream>
using namespace std;
void func(int&);
int main()
{
int a=10;
std::cout <<"变量 'a' 的值为:" <<a<< std::endl;
func(a);
std::cout << "现在变量 'a' 的值为:" <<a<< std::endl;
return 0;
}
void func(int &m)
{
m=8;
}
输出结果:
变量 'a' 的值为:10
现在变量 'a' 的值为:8
指针是一个存储另一个变量内存地址的变量。它使编程更加便捷,因为它持有某个变量的内存地址。
- 声明
我们可以通过在变量前添加'&'符号来声明引用变量。如果在表达式中使用此符号,它将被视为地址运算符。
在使用指针变量之前,我们应该声明一个指针变量,这可以通过在变量前添加'*'运算符来创建。
- 重新赋值
引用变量不能重新赋值。现在,我们来看一个简单的例子:
#include <iostream>
using namespace std;
void func(int&);
int main()
{
int i; // 变量声明
int k; // 变量声明
int &a=i;
int &a=k; // 错误
return 0;
}
上面的代码显示了多次声明'int &a'是不允许的错误。因此,上面的程序说明了引用变量不允许重新赋值。
而指针可以重新赋值。在使用链表、树等数据结构时,重新赋值很有用。
- 内存地址
在引用的情况下,引用和实际变量引用相同的地址。在实际变量被删除或超出作用域之前,新变量不会被分配给引用变量。
让我们通过一个例子来理解这种情况。
#include <iostream>
using namespace std;
void func(int&);
int main()
{
int i;
int &a=i;
std::cout << "变量 'a' 的内存地址为:" <<&a<< std::endl;
std::cout << "变量 'i' 的内存地址为:" <<&i<< std::endl;
return 0;
}
输出结果:
变量 'a' 的内存地址为:0x7fff078e7e44
变量 'i' 的内存地址为:0x7fff078e7e4
在指针的情况下,指针变量和实际变量的内存地址是不同的。让我们通过一个例子来理解这一点。
#include <iostream>
using namespace std;
int main()
{
int k;
int *p;
p=&k;
cout<<"变量 'p' 的内存地址为:" <<&p;
cout<<"\n变量 'k' 的内存地址为:" <<&k;
return 0;
}
输出结果:
变量 'p' 的内存地址为:0x7ffcc5c164b8
变量 'k' 的内存地址为:0x7ffcc5c164b4
- NULL值
不能将NULL值赋给引用变量,但是可以将NULL值赋给指针变量。
- 间接操作
指针可以具有指向指针的指针,提供多级间接。例如:
#include <iostream>
using namespace std;
int main()
{
int *p;
int a=8;
int **q;
p=&a;
q=&p;
std::cout << "变量 'q' 的值为:" <<*q<< std::endl;
return 0;
}
在上面的代码中,指针'p'指向变量'a',而'q'是一个双指针,它指向'p'。因此,我们可以说'p'的值是变量'a'的地址,'q'变量的值是'p'变量的地址。
输出结果:
变量 'q' 的值为:0x7ffd104891dc
在引用的情况下,引用到引用是不允许的。如果我们尝试这样做,C++程序将抛出编译时错误。
让我们通过一个例子来理解这种情况。
#include <iostream>
using namespace std;
int main()
{
int a=8; // 变量初始化
int &p=a; // 为变量'a'创建一个引用变量
int &&q=p; // 引用到引用是无效的,会抛出错误
return 0;
}
输出结果:
main.cpp: In function 'int main()':
main.cpp:18:10: error: cannot bind 'int' lvalue to 'int&&'
int &&q=p;
- 算术操作
我们知道可以对指针应用算术操作,称为"指针算术",但不能对引用应用算术操作。在C++中不存在"引用算术"。
让我们看一个指针的简单例子。
#include <iostream>
using namespace std;
int main()
{
int a[]={1,2,3,4,5}; // 数组初始化
int *ptr; // 指针声明
ptr=a; // 将基地址赋给指针ptr
cout<<"*ptr的值为:" << *ptr;
ptr=ptr+1; // 将ptr的值增加1
std::cout << "\n*ptr的值为:" << *ptr << std::endl;
return 0;
}
输出结果:
*ptr的值为:1
*ptr的值为:2
让我们通过一个例子来理解引用。
#include <iostream>
using namespace std;
int main()
{
int value=90; // 变量声明
int &a=value; // 将值赋给引用
&a=&a+5; // 引用变量不能进行算术运算,会抛出错误
return 0;
}
上面的代码会抛出编译时错误,因为引用变量不允许进行算术操作。