c++引用变量之结构(一)

引用是已经定义的变量的别名,改变别名其实也是改变变量的本身;

下面看看最基本的引用将会用到哪里——交换变量

swap(int *a,int *b)//指针引用解除引用交换变量
{
    *a=*a^*b;
    *b=*a^*b;
    *a=*a^*b;
}
swap(int &a,int &b)//这里是通过引用传递
{
    a=a^b;
    b=a^b;
    a=a^b;
}

实际代码如下

#include<iostream>
using namespace std;
void swapr(int *a,int *b)//指针引用解除引用交换变量
{
    *a=*a^*b;
    *b=*a^*b;
    *a=*a^*b;
}
void swapt(int &m,int &n)//这里是通过引用传递
{
    m=m^n;
    n=m^n;
    m=m^n;
}
int main(void)
{
    int a=10,b=100;
    swapr(&a,&b);
    cout<<a<<" "<<b<<endl;
    swapt(a,b);
    cout<<a<<" "<<b<<endl;
    return 0;
}

100 10
10 100

1.创建引用变量

c和c++使用&作为取地址符来指示变量的地址。在c++中它还有另外一个含义,将其用来声明引用,如上述解释。

例如:将rodents作为变量rats的别名,可以

int rats;
int &rodents=rats;

在这里&不是取地址符而是类型标识符的一部分。就像声明中的char *指的是指向char的指针一样。int &指的是指向int 的引用。上述引用声明的变量他们都指向相同的值和内存单元。

2.例子(包括引用变量作为函数参数和创建引用变量)

//c++将引用用于结构
#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()
{//在c++里定义一个结构体变量是不需要struct定义的(省略了)
    free_throws one ={"ifelsa branch", 13, 14};//赋值
    free_throws two ={"andor knott", 10, 16};
    free_throws three={"minner max", 7, 9};
    free_throws four={"whily looper", 5, 9};
    free_throws five={"long long", 6, 14};
    free_throws team={"throwgoods", 0, 0};
    free_throws dup;
    set_pc(one);//算出来第一个的percent
    display(one);//将他输出
    accumulate(team,one);//叠加,积累两个结构体成员变量中的值
    display(team);//输出
    display(accumulate(team,two));//展示与display(team)等效
    accumulate(accumulate(team,three),four);//将three与team叠加完之后,再与four叠加
    display(team);//team就是叠加完之后那个
    dup=accumulate(team,five);//结构体之间是可以赋值的
    std::cout<<"displaying team:\n";
    display(team);//输出team与上述dup是相同的
    std::cout<<"displaying dup after assignment:\n";
    display(dup);//输出dup检测一下
    set_pc(four);//把four的percent算出来
    accumulate(dup,five) =four;//赋值
    std::cout<<"displaying dup after ill_advised assignment:\n";
    display(dup);
    return 0;
}
void display(const free_throws & ft)//显示结构的内容但是不修改它,加上const修饰
{
    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)//计算百分比判断分母是否为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)//接收两个结构参数,并将第二个结构的成员attempts和made
//添加到第一个结构的相应成员中,只修改了第一个结构,因此第一个参数为引用,第二个参数为const引用
//但是我们发现这是有返回值的,display(accumulate(team,two))就可以解释了,
//首先将结构对象team作为第一个参数传给了accumulate(),这意味着在函数accumulate中,target指向的就是team,函数可以修改team
//再返回指向它的引用,return target是返回语句
//光看这一点并不能知道返回的是引用,但是函数头和原型指出了这一点
//如果返回值类型被声明free_throws而不是free_throws &上述语句将返回target(也就是team)的拷贝。但是返回类型是引用,这意味着返回的是最初传递给accumulate
//接下来将accumulate的返回值作为参数传递给display,这意味着team传递给了display()。display的参数作为引用,这意味着函数display中的ft指向的是team,因此
//将显示team的内容
{//累加函数
    target.attempts+=source.attempts;
    target.made+=source.made;
    set_pc(target);
    return target;
}

介绍一下程序 

这个程序首先初始化了多个结构对象。如果指定的初始值较少,余下的成员将会被设置为0

在上述代码中我们就需要注意const用法引用变量作为函数参数结构体定义的问题了

如果实参与引用参数不匹配,c++将生成一个临时变量。当前,仅当参数为const引用时,则编译器将在下面两种情况中生成临时变量:

1.实参的类型正确但不是左值。

2.实参的类型不正确但是可以转换成别的类型。

3.介绍左值

左值参数是可被引用的数据对象,例如,变量,数组元素,结构成员,引用和解除引用的指针都是左值。非左值包括字面常量(用括号括起来的字符串除外,他们由地址表示)和包含多项的表达式。在c语言中,左值最初指的是可出现在赋值语句左边的实体,但这是引入关键字const之前的情况。现在常规变量和const变量都可以视为左值,因为可以通过地址访问他们。但常规变量属于可修改的左值,而const属于不可修改的变量。

应该尽可能的使用const

将引用变量声明为常量数据的引用的里有有三个:

1.使用const可以避免无意中修改数据的编程错误

2.使用const使函数能够处理const和非const实参,否则将只能接受非const变量数据

3.使用const引用使函数能够正确的生成临时变量 

更深入的了解返回应用和传统返回机制的不同

传统返回机制与按值传递函数参数类似:计算关键字return后面的表达式,并将结果返回给调用函数。从概念上说,这个值被复制到一个临时位置,而调用程序将使用这个值

double m=sqrt(16.0);
cout<<sqrt(25.0);

在第一条语句,值4.0被复制到一个临时变量,然后被复制给m。在第二条语句中,值5.0被复制到一个临时位置,然后传递给cout

接下来我们看一行代码

dup=accumulate(team,five);

如果accumulate返回给一个结构,而不是指向结构引用,将把整个结构复制到一个临时变量,再将这个拷贝给dup。但在返回值为引用时,将直接把team复制到dup,效率更高

返回引用的函数实际上是被引用的变量的别名

返回时要注意的一点是,应避免返回函数终止时不再存在的内存单元引用。应避免写下面的代码

const free_throws & clone2(free_throws & ft)
{
    free_throws newguy;
    newguy = ft;
    return newguy;
}

该函数返回的是一个指向临时变量的引用,函数运行完之后它将不复存在。

为了避免这样的问题,最简单的方法就是,返回一个作为参数传递给函数的引用。作为参数的引用将指向调用函数使用的数据,因此返回的引用也将指向这些数据。

  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

forget hurt

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值