重载运算符后的返回值?

其实c语言没有引用这个概念,导致很多语言里的细节其实根本就是矛盾的。光光怪初学者领悟不了,其实有些冤枉。

 

int get_value_at(int* , int);

 

int x[20];

x[1] = 2;

*(x + 1) = 2;

get_value_at(x, 1) = 2; /// Compiling error!

 

x[1]是什么类型?*(x + 1)又是什么类型?

 

c语言玩弄了一个很geeker的技巧,试图用结果去说明原理

 

0)左值可放到等号左边,右值不可以。(这条规则被实际挑战的千疮百孔)

1)x[1]和*(x + 1)是一个左值

2)函数的非void返回值是个右值

3)x+1是一个右值

 

我们要讲道理,不能用行政命令指挥初学者的大脑:凭什么第一点的那几个操作的结果就这么特殊呢?

 

第一点确实是一个语言中的特例,这种特例在c语言中其实根本是由于语言的自完备性不足造成的:

1)如果把c语言看作是对汇编的封装,那么“变量”是对“一块连续内存的引用”这个概念的封装。

 

2)c语言封装了细节之后,又要允许人们去访问其中的细节(打破封装),问题就来了。

既然“变量”是对“一块连续内存的引用”,那我现在想访问这块连续内存中的“某一部分连续内存",这其实就是

x[1] = 2;

*(x + 1) = 2;

这一类操作。问题是这部分内存并没有一个变量来封装它们的引用(数组这块内存有变量封装,可惜数组的元素没有变量去封装),所以c语言又试图拿出左值,右值这些大杀器来说明这些场景。初学者不晕才怪。看我的解释:

 

3)x[1] = 2;可以看作是 int y; y=2; //这2个操作。但是要注意这个临时定义的变量和我们平时定义的变量略有不同:平时定义的变量包含分配内存这个操作(就是它要去封装的那块内存,“定义即分配”),而我们这里定义的y不分配内存,仅仅用来封装已经分配好的x[1]这块内存的引用。y是左值!

 

4)struct {int _0; int _1;} x; x._1 = 2; //这里的x._1和上面的x[1]其实也是一个操作:访问一个连续内存块(这里由数组换成了结构体)的部分内存(由通过下标访问改为了通过成员变量访问)的引用。

 

5)上面的y是左值还是右值取决于x是左值还是右值。部分服从整体,很好明白吧。

 

6)c++解除了对引用这个概念的封装,我们终于可以给3)中的y一个合法的语法身份并且完美的解释y的行为了:int &y = x[1]; y = 2; //y不会引起分配内存操作而且y只能固定的引用x[1]。

 

7)c++明确的把左值和右值划分开了:一个值要么是右值,要么是左值。左值可以取地址,右值不可以。引用类型既然引用的是内存,当然可以取地址,一定是左值,哪怕是做函数的返回值。当然最新的c++ 11草案又扩充了引用的概念,引用也可以是右值,暂且不提。

 

 

好了,好事多磨。终于到了本文想说的话了。像x[1],*(x+1)这些特殊的操作有哪些呢,他们有什么特征呢?

 

返回值是一个引用,是一个左值。

 

That's it! 我们用事实说话,观察stl中重载运算符的结果,归纳出这些特殊的运算符。

 

1.前置的++, --

2.=, +=, -=, *=, /= , &=, |=, ^=, <<=, >>=

3.[], *

4. , (comma, 逗号运算符,在boost的序列初始化等等一组件中可以见到它的重载)

5.不允许重载的运算符: . (dot, 点号运算符,访问结构体成员的 )

 

实际上->操作返回的依然是一个右值,一个指针的拷贝。

 

如果以后你重载运算符,一定要记得这些哦。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值