C++学习随笔(二)——引用

来源:互联网 发布:淘宝客订单一直失效 编辑:程序博客网 时间:2024/05/17 09:10

参考资料:

1、搜狗百科:http://baike.sogou.com/v8548349.htm?fromTitle=C%2B%2B%E5%BC%95%E7%94%A8

2、http://blog.sina.com.cn/s/blog_60281b700100ens2.html

3、http://www.cnblogs.com/Mr-xu/archive/2012/08/07/2626973.html


1、C++引用(c++ reference)是对C语言的重要扩充,,引用的表示方法与定义指针相似,用&代替了*。

2、引用的概念及定义:

引用声明的方法:类型标识符&  引用名 = 目标变量名;或   类型标识符  &引用名 = 目标变量名;(两者的区别于指针中的类似)

例如:int  a; int&  b =  a;

说明(1)&在引用中不是求地址运算,而是起到标示作用;

(2)类型标识符是目标变量的类型,例如int

(3)(很重要)声明引用时,必须同时对其进行初始化。如指针中,在使用指针前,一定要初始化指针(告诉指针的地址)

(4)引用声明完毕后,相当于目标变量有两个名称,即该目标原名称和引用名,一定不能再把该引用名作为其他变量的名称

a为原名称,b为目标引用名, 给b赋值:b=1等价于a=1.

(5)引用本身不占内存,系统也不给引用分配内存。因为声明一个引用不是新定义一个变量,它只辨识该引用是目标变量名的一个别名,它本身不是一种数据类型。

(6)不能建立引用的数组,因为数组是一个由若干个元素组成的集合,所以无法建立一个由引用组成的集合。但是可以建立数组的引用:

例如:const int (&ref) = {2, 3, 5};//为什么加上const?因为 {2, 3, 5}此时四个字面值的数组,是保持在代码里只读的属性,如果不加,则会编译错误,而且ref的复制也不会成功。

引用不产生对象的副本,仅仅是对象的同义词。因此引用在定义时需要马上被初始化,因为它必须是某个东西的同义词,不能先定义一个引用后才初始化。


3、引用的作用:

(1)传递可变参数

传统的c,函数在调用时参数是通过值来传递的,这就是说:函数的参数不具备返回值的能力,因此在传统的c中,如果函数的参数具有返回的能力往往是通过指针来实现的。

voidswapint(int&a,int&b)

{

int temp;

temp=a;

a=b;

b=temp;

}//调用该函数的c++方法为:swapint(x,y); c++自动把x,y的地址作为参数传递给swapint函数。

(2)给函数传递大型对象

当大型对象被传递给函数是,使用引用参数可以使参数传递效率得到提高,因为引用并不产生对象的副本,也就是参数传递是,对象无须复制。

///////重载运算符不能对指针单独操作,我们必须把运算数声明为 Set 类型而不是 Set * 

4、引用作为返回值:

  要以引用返回函数值,则函数定义时要按以下格式:
类型标识符 &函数名(形参列表及类型说明)
{函数体}
  说明:
  (1)以引用返回函数值,定义函数时需要在函数名前加&
  (2)用引用返回一个函数值的最大好处是,在内存中不产生被返回值的副本。

(3)不能返回局部变量的引用。这条可以参照Effective C++[1]的Item 31。主要原因是局部变量会在函数返回后被销毁,因此被返回的引用就成为了'无所指'的引用,程序会进入未知状态。

(4)不能返回函数内部new分配的内存的引用。这条可以参照Effective C++[1]的Item 31。虽然不存在局部变量的被动销毁问题,可对于这种情况(返回函数内部new分配内存的引用),又面临其它尴尬局面。例如,被函数返回的引用只是作为一个临时变量出现,而没有被赋予一个实际的变量,那么这个引用所指向的空间(由new分配)就无法释放,造成memory leak。

(5)可以返回类成员的引用,但最好是const。这条原则可以参照Effective C++[1]的Item 30。主要原因是当对象的属性是与某种业务规则(business rule)相关联的时候,其赋值常常与某些其它属性或者对象的状态有关,因此有必要将赋值操作封装在一个业务规则当中。如果其它对象可以获得该属性的非常量引用(或指针),那么对该属性的单纯赋值就会破坏业务规则的完整性。

(6)引用与一些操作符的重载:
  流操作符<<和>>,这两个操作符常常希望被连续使用,例如:cout << 'hello' << endl; 因此这两个操作符的返回值应该是一个仍然支持这两个操作符的流引用。可选的其它方案包括:返回一个流对象和返回一个流对象指针。但是对于返回一个流对象,程序必须重新(拷贝)构造一个新的流对象,也就是说,连续的两个<<操作符实际上是针对不同对象的!这无法让人接受。对于返回一个流指针则不能连续使用<<操作符。因此,返回一个流对象引用是惟一选择。这个唯一选择很关键,它说明了引用的重要性以及无可替代性,也许这就是C++语言中引入引用这个概念的原因吧。 赋值操作符=。这个操作符象流操作符一样,是可以连续使用的,例如:x = j = 10;或者(x=10)=100;赋值操作符的返回值必须是一个左值,以便可以被继续赋值。因此引用成了这个操作符的惟一返回值选择。

(7)在另外的一些操作符中,却千万不能返回引用:
+-*/ 四则运算符。它们不能返回引用,Effective C++[1]的Item23详细的讨论了这个问题。主要原因是这四个操作符没有side effect,因此,它们必须构造一个对象作为返回值,可选的方案包括:返回一个对象、返回一个局部变量的引用,返回一个new分配的对象的引用、返回一个静态对象引用。根据前面提到的引用作为返回值的三个规则,第2、3两个方案都被否决了。静态对象的引用又因为((a+b) == (c+d))会永远为true而导致错误。所以可选的只剩下返回一个对象了。

5、常引用和引用多态

(1)常引用声明方式:const 类型标识符&引用名=目标变量名;

用这种方式声明的引用,不能通过引用对目标变量的值进行修改,从而使引用的目标成为const,达到了引用的安全性。引用型参数应该在能被定义为const的情况下,尽量定义为const 。

(2)引用是除指针外另一个可以产生多态效果的手段。这意味着,一个基类的引用可以指向它的派生类实例。

【例】:

class A;

class B:public A{……};

B b;

A &Ref = b; // 用派生类对象初始化基类对象的引用

Ref 只能用来访问派生类对象中从基类继承下来的成员,是基类引用指向派生类。如果A类中定义有虚函数,并且在B类中重写了这个虚函数,就可以通过Ref产生多态效果。


引用总结:

(1)在引用的使用中,单纯给某个变量取个别名是毫无意义的,引用的目的主要用于在函数参数传递中,解决大块数据或对象的传递效率和空间不如意的问题。
  (2)用引用传递函数的参数,能保证参数传递中不产生副本,提高传递的效率,且通过const的使用,保证了引用传递的安全性。
  (3)引用与指针的区别是,指针通过某个指针变量指向一个对象后,对它所指向的变量间接操作。程序中使用指针,程序的可读性差;而引用本身就是目标变量的别名,对引用的操作就是对目标变量的操作。
  (4)使用引用的时机。流操作符<<和>>、赋值操作符=的返回值、拷贝构造函数的参数、赋值操作符=的参数、其它情况都推荐使用引用。


0 0