指针和引用

A、引用

一:引用

1、非const引用:int &i=j;

就是一个实体有两个名字,他们地址相同,因此可以相互并且同时改变。

2、const引用:指向const对象的引用

对于非const对象,引用必须用与该引用同类型的对象初始化。而对于const对象,引用可以绑定到不同但相关的类型的对象或者绑定到右值。例如

double dval=3.14;

const int &s=dval;

这里等价于

 double dval=3.14;

int temp=dval;

const int &s=temp;之所以可以这样是因为const引用是只读的,不会改变原始对象

二、什么时候返回引用是正确的

返回调用函数之前就已经存在的变量是正确的。

三、引用返回概念

类似函数参数类型.按值传递和引用传递,临时变量就相当于形参,他是拷贝的实参的值.引用返回就相当于引用传递.形参是实参的别名,其内存空间是一样的.
例如:A a(){...;return *this;}和A& a(){...;return *this;}中的值返回,*this相当于"实参",要用的时候他会拷贝一份给"形参"就是所谓的临时变量.然后通过临时变量来操作,用完后临时变量的空间是要释放的.所以最好不要用值返回做左值.而引用返回返回了一个对*this的引用,他们是一个内存空间,对返回值的操作实际就是对*this的操作.由于空间不会暂时释放,他可以做左值.

引用可以看成是指向固定地址的指针:A& a(){ return *this;} 就生成了一个固定地址的指针,并把指针带给你;但A a() { return *this;}会生成一个临时对象变量,并把这个临时变量给你,这样就多了一步操作。
C++中没有高效率的对象返回,所以返回值一定不要是一个直接的对象,除非是 return new A();,这种模式好象在vc++中专门做过优化的

问题的关键是,当你想要返回一个引用而不是一个拷贝时,你要确保这个引用的有效性,比如:int & fun() { int a; a=10; return a; }这样是不行的,因为a会在fun退出时被销毁,这时返回的a的引用是无效的(可以返回,只是无效而已,因为后期会被程序所覆盖)。这种情况下,如果fun的返回类型不是int & 而是int就没有问题了。因此,要返回一个引用时,“临时变量”不能是“临时”的,至少得等函数外部使用完毕这个引用之后,才能销毁它。

三、千万不要返回局部对象的引用或者指针 

int &fun()
{
 int str=7;
 return str;
}
int main()

 int &i=fun();
 cout<<i<<endl;

}

这里可以返回局部变量的引用,原因是:

1.用int i来接收函数返回值,这样即使局部变量被销毁,也对i的值没有影响
2.局部变量在一个函数返回以后,其值随时都可能被以后函数栈帧中的数据所覆盖,而这里只有一个函数所以没有覆盖的现象,main函数调用完了程序就结束了所以展现不了问题。

将程序改为:

int &fun()
{
 int str=7;
 return str;
}
int add(int a,int b)
{
 int i=a+b;
 return i;

}
int main()

 int &i=fun();
 cout<<i<<endl;
 add(4,5);
 cout<<i<<endl;

}

运行结果将根据编译器不同而发生变化,i得值前后不同,从而证明了,最好不要返回局部变量的引用或者指针

B、指向函数的指针

1、函数指针只能通过同类型的函数或函数指针或者0值常量表达式进行初始化和赋值。

2、函数指针可以不需要使用解引用操作符,直接通过指针进行调用函数

pf=lengthcompare;//lengthcompare是一个函数,pf是该类型的函数指针

pf('hi');与(*pf)('hi');意义相同

应用函数指针的例子:

//形式:返回类型(*函数名)(参数表)

char(*pFun)(int);

char glFun(int a){return;}

void main()

{

pFun =glFun;

(*pFun)(2);

}

3、int (*ff(int))(int*, int);

等价于 typedef int (*pf) (int *, int); pf ff(int);

注:typedef函数指针的用法

typedef 行为有点像 #define 宏,用其实际类型替代同义字。不同点:typedef 在编译时被解释,因此让编译器来应付超越预处理器能力的文本替换

用法一:见c++primer p239

typedef int (*MYFUN)(int, int);
这种用法一般用在给函数定义别名的时候
上面的例子定义MYFUN 是一个函数指针, 函数类型是带两个int 参数, 返回一个int。

分析这种形式的定义的时候可以用下面的方法:
先去掉typedef 和别名, 剩下的就是原变量的类型.
去掉typedef和MYFUN以后就剩:

int (*)(int, int)

用法二:

typedef给变量类型定义一个别名.

typedef struct{
int a;
int b;
}MY_TYPE;
未命名结构直接取了一个叫MY_TYPE的别名,这样如果你想定义结构的实例的时候就可以样:MY_TYPE tmp;

C、引用和指针的区别

引用更简洁、更安全,因为引用声明时必须初始化,引用更接近于const指针,一旦与某个变量关联,将一直效忠于他。

最后说一下引用的机制。很多人都在争论引用是怎么实现的?如果你看看vc做出的反汇编代码,你会发现在机器码的层次,指针与引用的实现是相同。但是,如果你以此断定引用就是指针,那么就错了。的确,引用是靠指针实现的,但是二者有区别。我们讨论引用的问题,一定要在c++的语言层面上讨论,而不能跑到汇编代码中去看。在c++中,引用就是个别名,本身不会另外分配空间。但是在汇编层次,你会发现“引用”有自己的空间。别忘了,你已经离开了c++的范围,这样的讨论失去了意义。总之,我们应该明白,c++中的引用就是个别名,具体的实现方法也要取决于编译系统和优化方案。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值