c++引用

64 篇文章 0 订阅

引用

  • 数据类型 &别名 = 原名;给原名起一个别名,访问同一块内存
  • 用多个变量名称访问同一个内存地址。
  • 引用必须初始化,初始化后不可以更改。不可以通过赋值操作改变引用。
  • 通过引用参数产生的效果和地址传参是一样的,但是引用语法更简单。
  • &不是地址运算符,而是类型标识符的一部分。int &指的是指向int的引用。
  • 引用与指针不同,是一种伪装指针。
  • 引用变量主要被用作处理结构体和类对象的函数的参数。
  • 如果一个类(如ofstream)是从另一个类(如ostream)派生出来,则基类引用可以指向派生类对象
  • 引用更接近const指针,如下所示:
int & rodents = rats;

int * const pr = &rats;

在这里插入图片描述

  • 引用常用作函数参数。
  • 在对函数的参数传递过程中,使用引用不改变原数据值时,使用const
double refcube(const double &ra);
  • 如果实参与引用参数不匹配,c++将生成临时变量(ra指向它)(函数调用期间存在),当前,仅当参数为const引用时,c++才允许这样做。
double refcube(const double &ra)
{
    return ra * ra * ra;
}

double side = 3.0;
double * pd = &side;
double & rd = side;
long edge = 5L;
double lens[4] = { 2.0, 5.0, 10.0, 12.0};
double c1 = refcube(side);        // ra is side
double c2 = refcube(lens[2]);     // ra is lens[2]
double c3 = refcube(rd);          // ra is rd is side
double c4 = refcube(*pd);         // ra is *pd is side
double c5 = refcube(edge);        // ra is temporary variable
double c6 = refcube(7.0);         // ra is temporary variable
double c7 = refcube(side + 10.0); // ra is temporary variable
  • 右值引用:使用&&声明
  • 引用用于结构体:结构体变量名free_throws
//strc_ref.cpp -- using structure references
#include <iostream>
#include <string>
struct free_throws
{
    std::string name;
    int made;
    int attempts;
    float percent;
};

void display(const free_throws & ft);
void set_pc(free_throws & ft);
free_throws & accumulate(free_throws & target, const free_throws & source);

int main()
{
// partial initializations – remaining members set to 0
    free_throws one = {"Ifelsa Branch", 13, 14};
    free_throws two = {"Andor Knott", 10, 16};
    free_throws three = {"Minnie Max", 7, 9};
    free_throws four = {"Whily Looper", 5, 9};
    free_throws five = {"Long Long", 6, 14};
    free_throws team = {"Throwgoods", 0, 0};
// no initialization
    free_throws dup;

    set_pc(one);
    display(one);
    accumulate(team, one);
    display(team);
// use return value as argument
    display(accumulate(team, two));
    accumulate(accumulate(team, three), four);
    display(team);
// use return value in assignment
    dup = accumulate(team,five);
    std::cout << "Displaying team:\n";
    display(team);
    std::cout << "Displaying dup after assignment:\n";
    display(dup);
    set_pc(four);
// ill-advised assignment
    accumulate(dup,five) = four;
    std::cout << "Displaying dup after ill-advised assignment:\n";
    display(dup);
    return 0;
}

void display(const free_throws & ft)
{
    using std::cout;
    cout << "Name: " << ft.name << '\n';
    cout << " Made: " << ft.made << '\t';
    cout << "Attempts: " << ft.attempts << '\t';
    cout << "Percent: " << ft.percent << '\n';
}
void set_pc(free_throws & ft)
{
    if (ft.attempts != 0)
        ft.percent = 100.0f *float(ft.made)/float(ft.attempts);
    else
        ft.percent = 0;
}

free_throws & accumulate(free_throws & target, const free_throws & source)
{
    target.attempts += source.attempts;
    target.made += source.made;
    set_pc(target);
    return target;
}
void set_pc(free_throws & ft); 
/use a reference to a structure

void display(const free_throws & ft); 
don't allow changes to structure

free_throws & accumulate(free_throws & target, const free_throws & source);
accumulate(accumulate(team, three), four);
/上式中如果返回值类型为:free_throws,返回值将左拷贝。
如果返回值类型为:free_throw &,返回的是当初传递给accumulate()的team对象。

引用做函数的返回值

  • 传统的返回机制与按值传递函数参数类似:计算return后面的表达式的值,整个值先被复制到一个临时位置,而调用程序再使用这个值。返回值为引用时,不会产生临时变量,直接复制对应值,这样效率更高。
    1.不要返回局部变量的引用
    2.函数的调用可以作为左值
    例子: func() = 888;
    在这里插入图片描述
    在这里插入图片描述
  • 返回引用时注意的问题:应该避免返回函数终止时,不再存在的内存单元引用。方法有以下两种:
    1.返回一个作为参数传递给函数的引用。
const free_throws & clone2(free_throws & ft)
{
    free_throws newguy; // first step to big error
    newguy = ft;        // copy info
    return newguy;      // return reference to copy
}

2.用new来分配新的存储空间。

const free_throws & clone(free_throws & ft)
{
    free_throws * pt;
    *pt = ft;     // copy info
    return *pt;  // return reference to copy
}使用clone()创建无名结构体,并创建结构体指针pt
  • 上述函数的使用:
free_throws & jolly = clone(three);
  • clone()隐藏了对new的调用,这样很容易忘记用delete来释放内存。

引用的本质

  • 在c++内部实现是一个指针常量
    在这里插入图片描述

常量引用

  • 例子:const int &a = 10; 此时编译器会临时创建一个temp:int temp = 10; const int &a = temp;
  • 多用于函数中
    在这里插入图片描述

引用用于类对象

  • 可以通过使用引用,让函数将类string,ostream,istream,ofstream,ifstream等类的对象作为参数
// strquote.cpp -- different designs
#include <iostream>
#include <string>
using namespace std;
string version1(const string & s1, const string & s2);
const string & version2(string & s1, const string & s2); // has side effect
const string & version3(string & s1, const string & s2); // bad design

int main()
{
    string input;
    string copy;
    string result;

    cout << "Enter a string: ";
    getline(cin, input);
    copy = input;
    cout << "Your string as entered: " << input << endl;
    result = version1(input, "***");
    cout << "Your string enhanced: " << result << endl;
    cout << "Your original string: " << input << endl;

    result = version2(input, "###");
    cout << "Your string enhanced: " << result << endl;
    cout << "Your original string: " << input << endl;

    cout << "Resetting original string.\n";
    input = copy;
    result = version3(input, "@@@");
    cout << "Your string enhanced: " << result << endl;
    cout << "Your original string: " << input << endl;

    return 0;
}

string version1(const string & s1, const string & s2)
{
    string temp;

    temp = s2 + s1 + s2;
    return temp;
}

const string & version2(string & s1, const string & s2) // has side effect
{
    s1 = s2 + s1 + s2;
// safe to return reference passed to function
    return s1;
}

const string & version3(string & s1, const string & s2)  **bad design**
{
    string temp;

    temp = s2 + s1 + s2;
// unsafe to return reference to local variable
    return temp;
}

何时使用引用参数

使用引用参数的主要原因有两个。
1.程序员能够修改调用函数中的数据对象。
2.通过传递引用而不是整个数据对象,可以提高程序的运行速度。

  • 当数据对象较大时(如结构和类对象),第二个原因最重要。这些也是使用指针参数的原因。这是有道理的,因为引用参数实际上是基于指针的代码的另一个接口。那么,什么时候应使用引用、什么时候应使用指针呢?什么时候应按值传递呢?下面是一些指导原则:
  • 对于使用传递的值而不作修改的函数。
    1.如果数据对象很小,如内置数据类型或小型结构,则按值传递。
    2.如果数据对象是数组,则使用指针,因为这是唯一的选择,并将指针声明为指向const的指针。
    3.如果数据对象是较大的结构,则使用const指针或const引用,以提高程序的效率。这样可以节省复制结构所需的时间和空间。
    4.如果数据对象是类对象,则使用const引用。类设计的语义常常要求使用引用,这是C++新增这项特性的主要原因。因此,传递类对象参数的标准方式是按引用传递。
  • 对于修改调用函数中数据的函数:
    1.如果数据对象是内置数据类型,则使用指针。如果看到诸如fxt(&x)这样的代码(其中x是int),则很明显,该函数将修改x。
    2.如果数据对象是数组,则只能使用指针。
    3.如果数据对象是结构,则使用引用或指针。
    4.如果数据对象是类对象,则使用引用。
  • 当然,这只是一些指导原则,很可能有充分的理由做出其他的选择。例如,对于基本类型,cin使用引用,因此可以使用cin>>n,而不是cin>>&n。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值