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;
}

上面的代码会抛出编译时错误,因为引用变量不允许进行算术操作。

标签: C++语言, C++语言教程, C++语言技术, C++语言学习, C++语言学习教程, C++语言下载, C++语言开发, C++语言入门教程, C++语言进阶教程, C++语言高级教程, C++语言面试题, C++语言笔试题, C++语言编程思想