C++_01_引用与指针

区别与联系

相同点:

  • 指针指向一块内存,它的内容是所指内存的地址;引用是某块内存的别名。

区别:

  1. 指针是一个实体,而引用仅是个别名;
  2. 引用使用时无需解引用(*),指针需要解引用;
  3. 引用只能在定义时被初始化一次,之后不可变;指针可变;引用“从一而终” _
  4. 引用没有 const,指针有 const,const 的指针不可变;
  5. 引用不能为空,指针可以为空;
  6. “sizeof 引用”得到的是所指向的变量(对象)的大小,而“sizeof 指针”得到的是指针本身(所指向的变量或对象的地址)的大小;typeid(T) == typeid(T&) 恒为真,sizeof(T) == sizeof(T&) 恒为真,但是当引用作为成员时,其占用空间与指针相同(没找到标准的规定)。
  7. 指针和引用的自增(++)运算意义不一样;

引用的主要功能

引用的主要功能是传递函数的参数和返回值。

C++语言中,函数的参数和返回值的传递方式有三种:值传递、指针传递和引用传递。

值传递:

void func1(int x)
{
    x += 10;
}
// ...
int a = 0;
func1(a);
cout << "a = " << a << endl; // a = 0

由于func1函数体内的x是外部变量n 的一份拷贝,改变x 的值不会影响a, 所以a 的值仍然是0.

指针传递:

void func2(int * x)
{
    * x = (* x) + 10;
}
⋯  
int b = 0;
func2(&b);
cout << "b = " << b << endl; // b = 10

由于func2 函数体内的x 是指向外部变量b 的指针,改变该指针的内容将导致b 的值改变,所以b 的值成为10.

引用传递:

void func3(int & x)
{
    x += 10;
}
//...  
int c = 0;
func3(c);
cout << "c = " << c << endl; // c = 10

由于func3 函数体内的x 是外部变量n 的引用,x和c 是同一个东西,改变x 等于改变c,所以c 的值成为10.

对比上述三个示例程序,会发现“引用传递”的性质象“指针传递”,而书写方式象“值传递”。实际上“引用”可以做的任何事情“指针”也都能够做,为什么还要“引用”? 指针能够毫无约束地操作内存中的如何东西,尽管指针功能强大,但是非常危险。

指针可以为空,引用不能为空。

这就意味着我们拿到一个引用的时候,是不需要判断引用是否为空的,而拿到一个指针的时候,我们则需要判断它是否为空。这点经常在判断函数参数是否有效的时候使用。

void fun1(int *point)
{
     // 为了代码的稳健和安全,我们需要判断指针是否有效,通常做法是判断指针是否为
     // 空,其他的判断就需要根据函数的具体功能来判断了
     if(!point)
     {
        return;
     }
     // 函数实现
}

void fun2(int &refence)
{
     // 在这里,我们就不用担心refence是否为空
}

// 作者:nkaifang
// 链接:https://www.zhihu.com/question/37608201/answer/90293843
// 来源:知乎
// 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

引用修饰函数参数还可以提高效率,例子如下:

Class Object
{// 实现省略,只需要知道我们在这里声明了一个类,在下面我们要将这个类的对象作为
 // 函数参数类型来使用};
void fun1(Object obj)
{
     // 此函数声明中,obj是值传递,会产生一个临时对象
}
void fun2(Object &obj)
{
    // 我们不用检查obj是否为空,同时,使用引用传递,可以避免临时对象
}

指针可以多次赋值,即在某时刻可以指向地址1,换个时候可以指向地址2,例如:

int a = 0;
int b = 1;
int *point = NULL;
point = &a;     // 在某个时刻,指针可以指向a
point = &b;     // 换个时刻,指针可以指向b

而引用则不同,引用只能在初始化的时候就指定了所引用的变量,对象等等,之后就不能改变了,用外号的例子来说就是"明明"这个外号在出现的时候就是代指小明,之后“明明”这个外号就绑在小明身上了,它不会过段时间换成小暗的外号。代码如下:

int xiaoming = 1;
int &refence_mingming = xiaoming;
int xiaoan = 2;
&refence_mingming = xiaoan;           // error,一个引用在初始化后就固定下来,不能再变化.

由以上可以,当我们需要某个是否指向为空的时候,我们就需要使用指针了,还有指向的对象需要变化的时候,我们也需要使用指针。其他地方一般推荐引用。

引用的本质

引用实际上就是基于指针加了一些语法糖,比如必须初始化、不能改变引用的指向等等。

但是引用是别名这是c++语法规定的语义,那么到底引用在汇编层面和指针有什么区别呢? 没区别。 对,引用会被c++编译器当做const指针来进行操作。

TODO


Reference:

posted @ 2022-06-11 17:54  吹不散的流云  阅读(29)  评论(0编辑  收藏  举报