C++ 引用 vs 指针
C++引用和指针看起来很相似,但它们之间有一些存在差异。引用是一个变量,它是现有变量的另一个名称,而指针是存储另一个变量地址的变量。
什么是引用
引用是一个变量,被称为已存在变量的另一个名称。变量的引用是通过存储另一个变量的地址来创建的。
引用变量可以被看作是具有自动间接性的常量指针。这里,自动间接性意味着编译器自动应用间接操作符(*)。
引用示例:
int &a = i;
在上述声明中,’a’是’i’变量的别名。我们也可以通过’a’变量来引用’i’变量。 让我们通过一个例子来理解。
#include <iostream>
using namespace std;
int main()
{
int i=8; // variable initialization
int &a=i; // creating a reference variable
cout<<"The value of 'i' variable is :"<<a;
return 0;
}
在上述代码中,我们创建了一个引用变量,即’a’变量对应的是’i’变量。在创建引用变量后,我们可以通过’a’变量来访问’i’的值。
指针是什么
指针是一个包含另一个变量地址的变量。可以通过(*)运算符解引用指针,访问指针指向的内存位置。
引用与指针的区别
以下是引用和指针的区别:
- 定义
引用变量是已存在变量的另一个名称。主要用于“按引用传递”,其中将引用变量作为参数传递给函数,函数对传递给它的变量的原始副本进行操作。
通过一个简单的例子来理解。
#include <iostream>
using namespace std;
void func(int &);
int main()
{
int a=10;
std::cout <<"Value of 'a' is :" <<a<< std::endl;
func(a);
std::cout << "Now value of 'a' is :" <<a<< std::endl;
return 0;
}
void func(int &m)
{
m=8;
}
将下面的英文翻译成中文,不解释,保留HTML格式:
输出:
Value of 'a' is :10
Now value of 'a' is :8
而, 指针 是一个存储另一个变量地址的变量。它使得编程更容易,因为它保存了某个变量的内存地址。
- 声明
我们可以通过在变量前添加“&”符号来声明引用变量。如果在表达式中使用该符号,则会被视为地址运算符。
在使用指针变量之前,我们应该声明一个指针变量,这个变量通过在变量前添加“*”运算符来创建。
- 重新赋值
我们不能重新赋值引用变量。现在,我们以下面的示例为例:
#include <iostream>
using namespace std;
void func(int &);
int main()
{
int i; // variable declaration
int k; // variable declaration
int &a=i;
int &a=k; // error
return 0;
}
上面的代码显示了多个声明 int &a是不允许的错误。因此,上面的程序得出结论,对于引用变量,重新赋值操作是无效的。
而指针可以重新分配。当我们使用数据结构如链表、树等时,重新分配是很有用的。
- 内存地址
对于引用而言,引用变量和实际变量都指向相同的地址。直到实际变量被删除或超出作用域,新变量才会被赋值给引用变量。
通过一个例子来理解这个情况。
#include <iostream>
using namespace std;
void func(int &);
int main()
{
int i;
int &a=i;
std::cout << "The address of 'a' variable is : " <<&a<< std::endl;
std::cout << "The address of 'i' variable is : " <<&i<< std::endl;
return 0;
}
输出:
The address of 'a' variable is : 0x7fff078e7e44 The address of 'i' variable is : 0x7fff078e7e4
上述输出显示引用变量和实际变量具有相同的地址。
对于指针而言,指针变量和实际变量将拥有不同的内存地址。让我们通过一个例子来理解这个问题。
#include <iostream>
using namespace std;
int main()
{
int k;
int *p;
p=&k
cout<<"The memory address of p variable is :"<<&p
cout<<"\nThe memory address of k variable is :"<<&k
return 0;
}
输出:
The memory address of p variable is :0x7ffcc5c164b8 The memory address of k variable is :0x7ffcc5c164b4
- 空值
我们不能将空值赋给引用变量,但指针变量可以被赋予空值。
- 间接访问
指针可以有指向指针的指针,提供多级间接访问。
#include <iostream>
using namespace std;
int main()
{
int *p;
int a=8;
int **q;
p=&a
q=&p
std::cout << "The value of q is : " <<*q<< std::endl;
return 0;
}
在以上的代码中,指针 ‘p’ 指向变量 ‘a’,而 ‘q’ 是一个指向 ‘p’ 的双指针。因此,我们可以说 ‘p’ 的值将是变量 ‘a’ 的地址,而 ‘q’ 的值将是变量 ‘p’ 的地址。
输出:
The value of q is : 0x7ffd104891dc
在引用的情况下,无法引用其他的引用。如果我们尝试这样做,c++程序将会抛出编译时错误。
让我们通过一个例子来理解这种情况。
#include <iostream>
using namespace std;
int main()
{
int a=8; // variable initialization
int &p=a; // creating a reference variable for ?a? variable.
int &&q=p; // reference to reference is not valid, it throws an error.
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}; // array initialization
int *ptr; // pointer declaration
ptr=a; assigning base address to pointer ptr.
cout<<"The value of *ptr is :"<<*ptr;
ptr=ptr+1; // incrementing the value of ptr by 1.
std::cout << "\nThe value of *ptr is: " <<*ptr<< std::endl;
return 0;
}
输出:
The value of *ptr is :1
The value of *ptr is: 2
让我们通过一个例子来理解这些参考资料。
#include <iostream>
using namespace std;
int main()
{
int value=90; // variable declaration
int &a=value; // assigning value to the reference
&a=&a+5 // arithmetic operation is not possible with reference variable, it throws an error.
return 0;
}
上述代码会抛出编译时错误,因为不允许对引用进行算术运算。