Cpp_引用

1.引用即别名

int a = 10;
int& b = a; // b引用了a,b是a的别名,b就是a,a就是b
/*
int b = a;
*/

引用必须做初始化,而且一经初始化其所引用的目标就不能更换。

引用对临时变量(匿名对象的作用)

任何出现字面值常量、计算表达式、类型转换、函数返回值的场合,都会有临时变量(匿名变量)产生。只能用带有常属性(const)的引用引用这样的临时变量,而且一旦通过引用引用了临时变量,那么该变量的生命期就会从语句级别被提升为与该引用同寿。

引用型函数参数

在c++中给一个函数传递参数有三种方法:1,传递对象本身。2,传递指向对象的指针。3,传递对象的引用。

1)如果函数的某个参数是引用,那么它就是该函数调用者实参的别名,对此引用的修改就是对其目标实参的修改,通过这种方法就可以从函数内部向其调用者输出数据。

2)通过引用向函数传递参数可以避免值传递所带来的内存复制开销,有助于提高传参的性能,但是也带来额外的风险,一旦在函数中修改了形参的值,也就等于修改了实参的值,如果这种修改并非预期,这种BUG就只能在运行阶段才会被发现。为了解决这个问题,可以将函数的参数定义为常引用,这样在函数中对常引用型参数的修改就会在编译阶段被暴露出来。

3)如果传递给函数的实参是临时变量,那么该函数的形参要么不用引用,要么就用常引用。

引用型函数返回值

1)左值和右值的概念
左值:可以放在赋值运算符左边的。可以被修改的。可以被取地址的。

int i;    //i就是左值
i = 10;
++i;
int* p = &i;

右值:只能放在赋值运算符右边的。不可被修改的。不可被取地址的。

字面值常量:10 = i; --10; int* p = &10; // 错误
表达式的值:a + b = c; (a+b)++; int* p = &(a+b); // 错误
值形式的函数返回值:int foo (void) { ... }
foo () = 10; ++foo (); int* p = &foo (); // 错误

2)如果一个函数返回类型被声明为引用,那么该函数的返回值就是一个左值。注意该引用的目标一定要在函数返回以后依然有效,否则其值将是未定义的。

3)为了避免从函数返回值所带来的内存复制开销,可以将函数的返回类型声明为引用,同时为了避免在函数外部修改函数返回引用的目标变量,可以为该引用附加常属性。

强调一个小问题,看看如下代码有何错误:

int &f1(); 

f1()=5; 
... 
... 
int &f1() { 
       int i; 
       int &ri=i; 
       return ri; 
} 

函数f1返回的引用ri是在函数体内声明的,一旦函数返回后,超出了函数作用域,ri所指向的内存区域,即对象i所占据的内存区域就被收回了,再对这片内存区域赋值会出错的。

引用的转换

是否可以声明一个引用,它具有int类型,却被初始化绑定到一个float类型的对象?如下列代码所示:

float f; 
int &rv=f;

结果证明这样的转换不能通过msvc++6.0的编译。但是引用的转换并非完全不可能,事实上一个基类类型的引用可以被初始化绑定到派生类对象,只要满足这两个条件:
1,指定的基类是可访问的。
2,转换是无二义性的。
例如:

class A  { 
 public: 
      int a; 
}; 
class B:public A{ 
  public: 
      int b; 
}; 
    A Oa; 
    B Ob; 
    A& mm=Ob; 
    mm.a=3; 

引用mm,它具有基类类型但被绑定到派生类对象Ob上。由于我们的这两个类都很简单,满足那两个条件,因此这段代码是合法的。
在这个例子中,mm和派生类Ob中的基类子对象是共用一段内存单元的。语句mm.a=3相当于Ob.a=3,但是表达式mm.b却是不合法的,因为基类子对象并不包括派生类的成员。

引用和指针

1)指针可以只定义不初始化,但是引用必须在定义的同时初始化。

2)指针的目标可以更换,但引用的目标不能更换。

3)可以定义指向指针的指针,但是不能定义引用引用的引用,没有高级引用:在2011标准中类似int&&的写法是合法的,但是它并不表示二级引用,而是表示右值引用。

4)可以定义存放指针的数组,但是不能定义存放引用的数组,可以定义引用数组的引用。

引用的实现机制

int&  __stdcallRefFun(int &n)//通过引用传递参数
{
n++;
return n;
}

int __stdcallValueFun(int n)//通过变量值传递参数
{
n++;
return n;
}

1.引用变量:
1)引用的内部实现为相当于一个指针变量,与指针的实现方式类似;
2)引用变量内存单元保存的指向变量地址(初始化时赋值),与指针不同地方时,引用变量在定义时必须初始化,而且使用过程中,引用变量保存的内存单元地址值是不能改变的(这一点通过编译器来实现保证);

3)引用也可以进行取地址操作,但是取地址操作返回的不是引用变量所在的内存单元地址,而是被引用变量本身所在的内存单元地址;

4)引用的使用,在源代码级相当于普通的变量一样使用,但在函数参数传递引用变量时,内部传递的实际是变量的地址值(这种机制的实现是通过编译器(编译手段)来实现的)。

关于汇编语言的补充

1.学习掌握汇编语言的原理(注:这里是原理学习,不是学习使用汇编语言进行代码编写),对提高软件开发者程序分析,提高对计算机系统实现原理的理解(如堆,栈,函数运行分析,以及掌握操作系统的运行实现机制,包括栈的生长方向等理解),都是非常有帮助;
2通过汇编分析,所有的实现机理都可以通过调试分析出来,对提高开发者的分析能力是非常有帮助的!包括对于C++的很多知识点,都可以通过反汇编分析,可以真正了解和掌握其背后的运行机理,提高对语言的正确运用;

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值