游戏开发论坛

 找回密码
 立即注册
搜索
查看: 6785|回复: 12

复习C++:引用

[复制链接]

13

主题

113

帖子

113

积分

注册会员

Rank: 2

积分
113
发表于 2007-9-21 20:32:00 | 显示全部楼层 |阅读模式
复习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、类的引用数据成员必须在构造函数的初始化列表中初始化。

18

主题

82

帖子

86

积分

注册会员

Rank: 2

积分
86
发表于 2007-9-22 09:08:00 | 显示全部楼层

Re:复习C++:引用

C++真是庞大,单引用就有怎么多内容好讲

76

主题

1100

帖子

1107

积分

金牌会员

Rank: 6Rank: 6

积分
1107
发表于 2007-9-22 17:33:00 | 显示全部楼层

Re:复习C++:引用

/*C++ 引用在游戏开发中很有用*/

#include <cstdlib>
#include <iostream>

using namespace std;

class myclass{
private:
static bool l;

public:
myclass (int &x,int &y){
if(x>y){
l==true;
cout<<"i>j is true"<<"\n";
}
else {
l==false;
cout<<"i>j is false"<<"\n";}
}

};

int main(){
int a=5,b=8;
myclass cobj(a,b);

system(&quotAUSE");
return 0;
}

45

主题

1163

帖子

1165

积分

金牌会员

Rank: 6Rank: 6

积分
1165
发表于 2007-9-22 18:17:00 | 显示全部楼层

Re:复习C++:引用

有错误,不知道大家发现没?

7、引用不能直接引用数组。
------ 不存在引用的数据,而不是引用不能引用数组,比如
    int array[16];
    int (&ref)[16] = array;
这就使数据的引用,完全合法。
而上面的
    int array[16];
    int &ref = array;          //错误
int[]和int两者类型完全是不一样的,连类型都不一样还怎么引用。

8、指针可以指向一个函数,而引用就不能直接引用函数(见effctive C++ 条款30)。
------ 以下语法是合法的
void foo( void )
{
    cout << "abc" << endl;
}
int main()
{
    void (&ref)( void ) = foo;
    ref();

    return 0;
}

86

主题

2251

帖子

2384

积分

金牌会员

Rank: 6Rank: 6

积分
2384
QQ
发表于 2007-9-23 01:52:00 | 显示全部楼层

Re:复习C++:引用

L3纯属乱用

就L3的乱写,我想说下自己对引用浅薄的认识,不对的话,望批评:

C++的引用其实和我们广义上谈论的引用是有一定区别的,我们经常谈论的的广义上的引用其实可以把指针包括进去。JAVA里的引用,倒比较贴近广义上的引用,而它可以看成一种为了安全性而做了限制的指针封装(避免了野指针)。C++的引用比JAVA的引用在功能上要弱得多,所以“别名机制”这个词更能反映C++引用的特性。

正因为C++引用很弱,且C++继承了C上的很多传统,所以习惯上引用的使用也要做一些限制。这里以函数声明为例子,看看我们应该遵守的一些限制:

首先是古老的C语言时代,我们的用法
void func(int a, int* b);
...
func(x, &y);
一个入了门的C程序,看到这样的接口,很容易做出这样的理解
x只是传值进入函数内,不用担心x被这个函数改变了值
y是传址进入函数内的,这意味着y是会被改变的。尤其对于基本类型来说,以传址的方式进入函数内,潜台词就是“我一定会被改变”。把一个基本类型传址,又不改变它的值,不是吃饱了撑着么……

以上可以说是来自C的老传统,老风格,而且比较优良。而到了C++上,因为多了一个引用,也就在语法上多了一项可以破坏这种风格的特性:
void func(int& a, int& b);
...
func(x, y);
如果以经典的C程序员的眼光看,x和y在func执行后,其值不会改变。但这是段C++代码,所以鬼知道它们俩是不是在func的小黑屋被干了。如此,传统被打破。

比较一下,多写个取址符遵守传统,和少写个取址符违背传统,我觉得前者好,更加直观,更精确。所以对于引用的应用一定要考虑清楚,像const引用做参数类型这样的使用方法,正是一种恰到好处的用法,因为它不仅遵守了传统,而且弥补了传统的不足(C里,我们不得不用取址,传一个不会被改动的对象,这样的代码很丑陋,而且制造了参数设计风格的不和谐)。

103

主题

1432

帖子

1458

积分

金牌会员

Rank: 6Rank: 6

积分
1458
QQ
发表于 2007-9-23 09:39:00 | 显示全部楼层

Re:复习C++:引用

楼主对c++的语法理解还存在很多错误。

引用是指针的隐藏形态,他的使用方法和普通变量一样,但其内在实质,其实是指针。理解这个就好理解什么是引用了。

第二个楼主的问题,将细节和具体的内容死记硬背,但是忽略了最基本的常识。那就是类型相容。其实除非你是教师,否则整天将那些示例挂在嘴上没有太多意义,中国的教育也是这样,有点忽略重点,浪费体力的感觉。

所谓类型相容,就是赋值的左边和右边类型应该是可以相容的,否则不能赋值。这是强类型语言的一大特点,可以保证程序逻辑的正确性。

要做到类型是否相容的判断,首先应该识别类型:

int i;

这里,i是变量名,不管多么复杂的类型声明,都会有一个中心语,那就是变量名。所有其他都是修饰这个中心语的。如果是复杂的类型声明,就存在修饰的顺序问题。

有一个相当简单的方法,那就是“先中间(i),然后右边,然后左边”。

当然,首先要懂得几个基本的符号代表什么。[] 代表数组,数组一定得有大小的,没有大小是不完全的,同时大小不同的数组,也是完全不相同的类型。 ( ) 代表函数,这个要和小括号区分开来,小括号是改变顺序用的,他一般包含中心语,但是函数符号只会在中心语右边。 & 代表引用,引用的语法意义就是别名,他不存在实体,也就是他不能被进一步修饰。 const 这个是常量指示,他会成为类型的一部分,表示该类型不可修改。 const 类型不能传递给非const类型。 const 修饰左边相邻的类型。

还有,[]() 只在右边, & * 只在左边,但可以借助小括号来改变顺序。

int const (*(*p)[7])( void* );

=》 p * [7] * ( void* ) const int;
p 是 指针。
指向大小为7的数组。
数组类型是指针。
而这个指针指向函数。
这个函数类型是 int const ( void* );

基本不能翻译成汉语,太复杂了,但是用来识别类型相容很容易。

int const func( void* v )
{
        int const (*array[7])( void* );
        array[0] = func;
        int const (*(*p)[7])( void* );
        p = &array;
        return (int const)p;
}

能轻易理解这个,就算过关了。
当然,不是所有类型都可以组合在一起的,自己慢慢尝试吧。

13

主题

113

帖子

113

积分

注册会员

Rank: 2

积分
113
 楼主| 发表于 2007-9-23 18:50:00 | 显示全部楼层

Re:复习C++:引用

非常感谢几位大哥的指点! 这样我才有提高啊!欢迎更多的人发表自己的意见。

76

主题

1100

帖子

1107

积分

金牌会员

Rank: 6Rank: 6

积分
1107
发表于 2007-9-24 14:42:00 | 显示全部楼层

Re:复习C++:引用

fm晕啦,哈哈.只是实际练习时发现引用瞒有用的,所以基本到处都想用用.容易造成乱用.
const的几类用法比较头晕.主要没太理解他在实际游戏开发中的用途.谁能结合实际开发例子讲解下.

86

主题

2251

帖子

2384

积分

金牌会员

Rank: 6Rank: 6

积分
2384
QQ
发表于 2007-9-24 15:05:00 | 显示全部楼层

Re:复习C++:引用

找个别人写的字符串类看看,应该比较有代表性,好像id的代码里就有

45

主题

1163

帖子

1165

积分

金牌会员

Rank: 6Rank: 6

积分
1165
发表于 2007-9-25 17:28:00 | 显示全部楼层

Re:复习C++:引用

int const (*(*p)[7])( void* );
先中间,再右边,再左边。好方法啊,学习了。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2025-2-28 06:27

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表