|
复习C++:引用
大四快毕业了,很有必要把大学的知识总结归纳.C++的细节很多,知识点很零碎,我综合大学里面记的几本笔记,还有《C++ primer》《Thinking in C++》《Effective C++》。把各个章节总结复习。我把文章放在这里,是让大家来看,来思考,来找出不足的地方。如果您有关于本文的意见,可以在后面跟贴,或者Email:lhwy01@163.com,或者发短信至15886425009告诉我。
一、理解引用。
引用既别名。也就是说引用是对一个对象名字的替代物。所有对引用的操作都直接影响到被引用的原始对象。有些书上说引用就是const指针,的确引用的行为类似const指针,但绝不能把它理解成const指针。因为指针是一个量,在内存中占据一块地方的,而引用是对象的别名,当然引用也可能占用一块存储空间,这取决于编译器的实现。总之,应当把引用理解成对象的别名,记住:“引用既别名”。
int iData;
int &ref = iData; //引用
int * const pointer = &iData; //const指针
cout << &iData << endl; //输出的是iData的地址
cout << &ref << endl; //输出的是iData的地址
cout << &pointer << endl; //输出的是pointer的地址
cout << &(*pointer) << endl; //输出的是iData的地址
二、引用与指针
引用很容易让人联想到指针,的确两者有相似地方,但更应当看到它们的不同之处:
1、引用必须在声明时既初始化,而指针不必。
2、引用一经初始化,就不能让它去引用另一个对象;而指针可以指向另一个对象。
3、引用不能为空;而指针可以。
4、引用不能new;而指针可以。
5、指针可以有指向指针的指针这种多级结构,而引用不能。
6、指针作加减运算是改变所指的对象,而引用的运算是改变所引用对象的值。
7、引用不能直接引用数组。
8、指针可以指向一个函数,而引用就不能直接引用函数(见effctive C++ 条款30)。
9、不存在指向引用的指针。
说明一下第4点:
MyClass &ref = new MyClass; //错误
MyClass *&pref = new MyClass; //错误
MyClass *p = new MyClass; //正确
MyClass &ref = (*p); //正确
delete &ref; //正确
所以,要分清对象和对象的引用,必须先有对象才能有对象的引用!!!
说明一下第7点:
int array[16];
int *p = array; //正确
int &ref = array; //错误
int *&pref = array; //错误
int *&pref = p; //正确
指针可以替代引用吗?引用能做的东西,指针也能实现,是这样吗?其实不然,C++中在一些地方,必须要用到引用:比如类的拷贝构造函数和某些运算符重载。关于它们,将另外专门讨论。
三、引用与函数:
1、引用作函数参数时会起到两个作用:
(1)避免参数传递的开销。如果直接传递参数,所传递的是参数的一个拷贝。如果参数是类对象,那么还会造成临时对象的创建,并调用构造和析构函数。使用引用就可以避免产生参数的拷贝和临时对象的创建。从而减少程序的开销。
(2)使函数能直接操作实参,也就是函数通过操作形参来操作实参。当然这个用指针也可以实现,但引用看上去更容易理解,可读性也更强。
注意在C++中有一个例外:异常处理中的catch中使用引用作参数时,所引用的其实是一个对象的拷贝而不是原对象!!!
在设计函数的参数时考虑上面两个作用,如果只想减少参数传递的开销,而不想实参被函数改动,可以加上const。
2、引用作函数返回值:
引用作函数返回值的作用与引用作函数参数的作用类似。但应注意:
(1)不要返回函数的局部变量的引用。
(2)不要返回函数内部用new初始化的指针的引用。
(3)不要返回对类非公有数据成员的非const引用。
这三点在effective C++(见条款30、31)中讲得很清楚。在设计函数时,如果返回值或实参可能是一个空对象,也应当使用指针而不是引用。
3、不要把表达式或临时变量传递给非const引用参数
void fun1( int &ref );
int fun2();
fun1( 3 ); //错误
fun1( 3 + 3 ); //错误
fun1( fun2() ); //错误
void fun1( const int &ref );
fun1( 3 ); //正确
fun1( 3 + 3 ); //正确
fun1( fun2() ); //正确
四、引用的用处:
引用的用处可以归纳为四点:
(1)在语法上增强可读性。有时候会出现a.b.c.d或xxxx->xxx->xx->x等的一长串的内容,让人写得累,看得也累。这时可以用引用代替它:X &x_ref = xxxx->xxx->xx->x; 这样就可以用x_ref而不是一长串的内容了。
(2)作函数参数和返回值时减少程序开销。
(3)作函数参数和返回值时能让函数直接操作参数或让调用者操作返回值。
(4)作函数参数时避免使用二级指针。指针是非常头痛的东西,二级指针就更容易让人糊涂。而在有些时候,我们要往函数传递指针的地址,就可能用到二级指针,有了引用就可以使用引用指针的引用从而避免使用二级指针了。
总结:
1、引用必须在声明时即初始化。
2、引用不能为空。
3、分清对象和对象的引用,必须先有对象才能有对象的引用,所以引用不能new。
4、不要直接引用数组。
5、不存在指向引用的指针。
6、引用作函数参数和返回值时避免了对象的拷贝的开销。
7、不要返回函数的局部变量的引用。
8、不要返回函数内部用new初始化的指针的引用。
9、不要返回对类非公有数据成员的非const引用。
10、不要把表达式或临时变量传递给非const引用参数
11、尽量用引用而不是二级指针。
12、类的引用数据成员必须在构造函数的初始化列表中初始化。 |
|