美文网首页
【C++拾遗】详解C++中的引用变量

【C++拾遗】详解C++中的引用变量

作者: 超级超级小天才 | 来源:发表于2019-08-12 21:17 被阅读0次

这是C++类一些重点难点知识笔记的第 四 篇,同专题的其他文章可以移步:https://www.jianshu.com/nb/39156122

引用变量被定义为一个变量的别名,即引用变量和其指向的变量代表同一个值,指向同一个存储单元,并且引用变量自从赋值起就已知跟着这个变量,不会再发生改变,也就是一个变量两个名字,所以更改其中的任何一个这个变量都会发生改变。

&符号可以指示变量的地址,同时它的另一个含义就是用来声明引用:

int genius;
int & me = genius;

这里的&不是地址运算符,而是类型标识符的一部分,就像int *int类型的指针一样,int &是指向int的引用。上述声明将me和genius等价,它们指向相同的值和内存单元,就是说me就是genius,而genius就是me。

引用和指针

引用和指针貌似很相像,例如:

int genius = 100;
int & me = genius;
int * myself = &genius;

这样,神奇的事情来了:

me == *myself == genius
&me == myself == &genius

引用与指针也有区别,例如必须再声明时将引用的值初始化,不能像指针一样,先声明在赋值;而且引用变量一旦赋值将不会再更改,这一点更接近于const指针:

int & me = genius;
int * const myself = &genius;

从而,me == *myself

将引用用作函数参数

按值传递与按引用传递

  • 按值传递:函数复制一份传入的值,然后对复制的数据进行操作,与被传入的数据无关
  • 按引用传递:函数直接使用传入的数据,不对其进行拷贝,修改的内容会直接体现在原数据上,这一点可以轻松地使用引用变量完成,抑或通过使用指针传递变量的地址来完成
按值传递与按引用传递

例如,完成一个交换两个变量的值的函数:

按值传递

void swapByValue(int a, int b)
{
    int temp = a;
    a = b;
    b = temp;
}

按引用传递:

void swapByReference(int & a, int & b)
{
    int temp = a;
    a = b;
    b = temp;
}

按地址(指针)传递:

void swapByPoint(int * a, int * b)
{
    int temp = *a;
    *a = *b;
    *b = temp;
}

三种函数的调用方式:

swapByValue(intA, intB);
swapByReference(intA, intB);
swapByPoint(&intA, &intB);

可以看出,按指针传递的声明方法和调用方法与其他两种均不同,需要在函数定义时告知传入的变量时 int* 类型,在调用时传入变量的地址 &intA 才可以;按值传递和按引用传递的调用方式相同,直接将变量名传入,只有在定义函数处才可以直到两者的不同,一个是按值传递,一个指出了是按地址传递 & int

按引用传递的一个重要方面是被传入的值会被直接使用或者修改,例如:

int squareByValue(int a)
{
    a *= a;
    return a;
}

int squareByReference(int & a)
{
    a *= a;
    return a;
}

调用时会出现:

int a =2;
cout << squareByValue(a) << " = square of " << a; // 输出:4 = square of 2
cout << squareByReference(a) << " = square of " << a; // 输出:4 = square of 4

可见,按照引用传递时,被传入的变量的更改会影响到原始的变量。

将引用用于结构

声明一个结构

struct myStruct
{
    int myInt;
    double myDouble;
}

将引用用于结构

将结构的引用作为参数传递非常简单,同时需要注意的是最好使用引用作为返回值。否则的话,函数需要先将待返回的结构体赋予一个临时变量,然后将这个临时变量返回,这是非常耗费时间和空间的。所以应该像这样使用它们:

myStruct & sum(myStruct & target, const myStruct & source)
{
    target.myInt += source.myInt;
    target.myDouble += source.myDouble;
    return target;
}

调用该函数:

myStruct target = {1,2.5};
myStruct source = {2,3.8};
myStruct result;
result = sum(target, source);

对返回值使用const

如果不对返回值使用const,意味着返回值是可以被赋值的,即下边的表达式成立:

sum(target, source) = anotherStruct;

未来避免这种情况发生,可以使用const限定返回值:

const myStruct & sum(myStruct & target, const myStruct & source);

从而如下的语句都不能成立:

sum(target, source) = anotherStruct;
sum(sum(target, source), source);

因为无法将一个有const限定的变量传递给一个没有const限定的变量,但是可以将返回值赋给其他结构:

result = sum(target, source);

何时使用引用参数

使用引用参数的主要原因有两个:

  • 程序员能够修改调用函数中的数据对象
  • 通过传递引用而不是整个数据对象,可以提高程序的运行速度

当数据对象较大时(如结构和类对象),第二个原因最重要。这些也是使用指针参数的原因。这是有道理的,因为引用参数实际上是基于指针的代码的另一个接口。那么,什么时候应使用引用、什么时候应使用指针呢?什么时候应按值传递呢?下面是一些参考原则

  • 对于使用传递的值而不作修改的函数
    • 如果数据对象很小,如内置数据类型或小型结构,则按值传递
    • 如果数据对象是数组,则使用指针,因为这是唯一的选择,并将指针声明为指向const的指针
    • 如果数据对象是较大的结构,则使用const指针或const引用,以提高程序的效率。这样可以节省复制结构所需的时间和空间。
    • 如果数据对象是类对象,则使用const引用。传递类对象参数的标准方式是按引用传递
  • 对于修改调用函数中数据的函数
    • 如果数据对象是内置数据类型,则使用指针
    • 如果数据对象是数组,则只能使用指针
    • 如果数据对象是结构,则使用引用或指针
    • 如果数据对象是类对象,则使用引用

转载请注明出处,本文永久更新链接:https://blogs.littlegenius.xin/2019/08/12/【C-温故知新】四函数/引用变量

相关文章

  • 【C++拾遗】详解C++中的引用变量

    这是C++类一些重点难点知识笔记的第 四 篇,同专题的其他文章可以移步:https://www.jianshu.c...

  • C++基础

    C++ 值传递、指针传递、引用传递详解C++中引用传递与指针传递区别 引用传递和指针传递的区别 引用的规则:(1)...

  • c++ 引用

    概念 c++中,变量的引用就是变量的别名,因此引用(reference)又成为别名(alias)。 变量的引用 i...

  • 右值引用

    参考资料 谈谈 C++ 中的右值引用C++11 左值、右值、右值引用详解

  • c++变量的引用

    本文简单介绍c++变量的引用,在c++当中“引用”就是变量的别名,相当于给变量再起一个名字。 使用&符号来为a和b...

  • * 与 & 区别

    基本概念 C++ 是 C 语言的超集。C++ 有一种C 语言不存在的变量类型 --- 引用变量(简成引用)。 指针...

  • C++要点回顾(谭爷爷的书)

    变量的引用 在C++中,变量的引用就是变量的别名alias 对一个变量的引用的所有操作,实际上都是对其所代表的原来...

  • Java基础-引用类型

    1.在Java中,引用类型的变量非常类似于C/C++的指针。引用类型指向一个对象,指向对象的变量是引用变量。这些变...

  • 在某些情况下,实参与引用参数不匹配,C++将生成临时变量

    如果实参与引用参数不匹配,C++将生成临时变量。当前,仅当参数为const引用时,C++才允许这样做。如果引用参数...

  • C/C++基础(5)

    C++ namespace 引用 引用的本质是变量的别名int a = 10;int &b = a;"数据类型 &...

网友评论

      本文标题:【C++拾遗】详解C++中的引用变量

      本文链接:https://www.haomeiwen.com/subject/isvpjctx.html