"&&","||"逻辑重载操作符的缺陷

大家,都知道"&&","||"拥有"短路"功能

  • 比如a=(0&&b) :  由于第一个操作数为0,所以不会去判断b的内容,直接执行a=0
  • 比如a=(-100||b): 由于-100不为0,所以不会去判断b的内容,直接执行a=1

可以参考下面代码:

int func(int i)
{
cout << "i = " << i << endl;
return i ;
} int main()
{
int a= (func()||func());
cout<<"a = " << a <<endl;
return ;
}

运行打印:

i=
a=

并没有调用func(100)函数,同样"||"逻辑操作符也具有拥有"短路"功能

而在重载操作符下,"&&","||"就不会具备"短路"功能

参考以下示例:

class Test
{
int mValue; public:
Test(int v)
{
mValue = v;
} int value() const
{
return mValue;
}
}; bool operator && (const Test& l, const Test& r) //&&重载操作符
{
return l.value() && r.value();
} Test func(Test t)
{
cout << "value()= " << t.value() << endl;
return t;
} int main()
{
  Test t0();
  Test t1();
  int b= (func(t0)&&func(t1));
  cout<<"b = " << b <<endl;
}

打印:

value()=             //进入func(t1)
value()= //进入func(t0)
b =

从结果看出,调用了func(t0)和func(t1),并且调用顺序是从右往左的.

这是因为执行func(t0)&&func(t1)时:

编译器实际是执行的operator && (func(t0), func(t1))函数,所以需要进入func()初始化两个参数

然后通过下面代码, 发现参数初始化顺序是从右往左的:

int print(int t)
{
cout<<t<<endl;
return t;
}
void func(int a,int b,int c)
{ } int main()
{
func(print(),print(),print());
return ;
}

运行打印:

","逗号重载操作符的分析

首先回顾下编译器自带的","逗号操作符

  • 逗号表达式前N-1子表达式不需要返回值
  • 逗号表达式从左往右计算,且最终的值等于最后一个表达式的值

比如:

int i=,b=;
int a =(i++,i++,b+,b=,i++); // b=5,且a=(i++)=7,该行运行后,i便等于8
(i,b,a)=; //a=10,i和b不变
  • 逗号表达式,通过()圆括号来表示

比如:

int a[][]={ (,,),
(,,),
(,,) }; //只初始化了a[0][0]=3, a[0][1]=6, a[0][2]=9

而在重载操作符下, ","逗号就不会具备从左往右计算的功能了

重载逗号注意事项

  • 尽量使用全局函数来重载
  • 逗号重载函数的参数必须有一个是class类的类型 (让编译器知道这个,逗号是用户重载的)
  • 逗号重载函数的返回值类型必须是引用(因为有可能要对返回值进行运算)
  • 逗号重载函数的返回值必须是最后一个参数的值(","逗号操作符的特性)

参考以下示例

#include <iostream>
#include <string> using namespace std; class Test
{
int mValue;
public:
Test(int i)
{
mValue = i;
} int value()
{
return mValue;
} Test operator +(int i) //重载 + 逗号操作符
{
Test ret=this->mValue +i;
cout<<ret.mValue<<endl;
   return ret;
} }; Test& operator , (const Test& a, const Test& b) //重载 ,逗号操作符
{
return const_cast<Test&>(b);
} int main()
{
Test t1();
Test t2();
Test t3=(t1+,t2+);return ;
}

运行打印:

                         //从最右侧执行t2+1
//最后执行t1+1

和之前分析的"&&","||"逻辑重载操作符缺陷一样:

编译器实际是执行的operator , (t1+1, t2+2)重载操作符函数.

由于初始化参数的顺序是从右往左初始化的,所以执行顺序变反了,先执行t2+2.

总结:

其实使用编译器自带的","逗号操作符,用在对象上也能成功,因为","主要就是用来隔离代码运行,并返回最后一个参数的值.不会参与对象的运算.

所以在以后的开发中,不要重载","逗号操作符

20.C++- "&&","||"逻辑重载操作符的缺陷、","逗号重载操作符的分析的更多相关文章

  1. C++ Primer笔记10_运算符重载_赋值运算符_进入/输出操作符

    1.颂值运营商 首先来福值运算符引入后面要说的运算符重载.上一节说了构造函数.拷贝构造函数:一个类要想进行更好的控制.须要定义自己的构造函数.拷贝构造函数.析构函数.当然,还有赋值运算符.常说的三大函 ...

  2. 5.8 C++重载自增与自减操作符

    参考:http://www.weixueyuan.net/view/6386.html 注意: 自增“++”与自减“--”都是一元操作符,其前置和后置两种形式都可以被重载. 前置 stopwatch ...

  3. C# 空合并操作符(??)不可重载?其实有黑科技可以间接重载!

    ?? 操作符叫做 null-coalescing operator,即 null 合并运算符.如果此运算符的左操作数不为 null,则此运算符将返回左操作数:否则返回右操作数. 在微软的官方 C# 文 ...

  4. JavaScript操作符(关系操作符、相等操作符和条件操作符)

    关系操作符用于对两个值进行比较,返回一个布尔值.关系操作符包括大于(>),小于(<),大于等于(>=),小于等于(<=).当关系操作符用于非数值时,也要先进行数值的转换.如 v ...

  5. C++:成员运算符重载函数和友元运算符重载函数的比较

    5.2.4 成员运算符重载函数和友元运算符重载函数的比较 (1)对双目运算符而言,成员运算符重载函数参数表中含有一个参数,而友元运算符重载函数参数表中有两个参数:对于单目运算符而言,成员运算符重载函数 ...

  6. Win32 API编程:WinMain无法重载函数或_tWinMain无法重载

    #include "windows.h" #include "tchar.h" int APIENTRY _tWinMain( HINSTANCE hInsta ...

  7. NDK(20)JNI的5大性能缺陷及优化技巧

    转自 : http://www.ibm.com/developerworks/cn/java/j-jni/index.html JNI 编程缺陷可以分为两类: 性能:代码能执行所设计的功能,但运行缓慢 ...

  8. C++ Primer : 第十四章 : 重载运算与类型转换之重载运算符

    重载前须知 重载运算符是特殊的函数,它们的名字由operator和其后要重载的运算符号共同组成. 因为重载运算符时函数, 因此它包含返回值.参数列表和函数体. 对于重载运算符是成员函数时, 它的第一个 ...

  9. 从零开始学C++之运算符重载(三):完善String类([]、 +、 += 运算符重载)、>>和<<运算符重载

    在前面文章中使用过几次String类的例子,现在多重载几个运算符,更加完善一下,并且重载流类运算符. []运算符重载 +运算符重载 +=运算符重载 <<运算符重载 >>运算符重 ...

随机推荐

  1. Hi3531用SPI FLASH启动 使用Nand做文件系统

    1.编译内核(可选) make ARCH=arm CROSS_COMPILE=arm-hisiv200-linux- menuconfig make ARCH=arm CROSS_COMPILE=ar ...

  2. sdl的缩放问题

    SDL是一种既是开源的,也是跨平台的多媒体开发包,在各种平台上应用很广,经常和FFMPEG等解码器同时使用.对于在windows mobile等缺乏通用播放器的平台来说,是一种很好的选择.网上很多代码 ...

  3. 打开CSDN论坛出现403

    打开CSDN论坛出现403 在查找资料的过程中,出现"403-禁止访问"

  4. 使用EFI引导从硬盘(U盘)安装Win7的图文教程

    目前仅支持vista后的64位系统 大部分使用EFI引导安装Win7的教程都是采用光盘启动安装,虽然光盘安装比较简单,但是对于没有光驱的朋友来说还是相当不便,更不用说光盘安装的两大缺点了,一速度慢,二 ...

  5. Caused by: java.lang.ClassNotFoundException: javax.persistence.NamedStoredProcedureQuery

    1.错误描述 2014-7-12 21:06:37 org.hibernate.engine.jdbc.internal.LobCreatorBuilder useContextualLobCreat ...

  6. HTML中设置背景图的两种方式

    HTML中设置背景图的两种方式 1.background    background:url(images/search.png) no-repeat top; 2.background-image ...

  7. I2C总线通讯协议

    I2C总线通讯协议 1. I2C总线简介 I2C是Inter-Integrated Circuit的简称,读作:I-squared-C.由飞利浦公司于1980年代提出,为了让主板.嵌入式系统或手机用以 ...

  8. C#图解教程 第十九章 LINQ

    LINQ 什么是LINQLINQ提供程序 匿名类型 方法语法和查询语法查询变量查询表达式的结构 from子句join子句什么是联结查询主体中的from-let-where片段 from子句let子句w ...

  9. 用VSCode开发一个asp.net core2.0+angular5项目(5): Angular5+asp.net core 2.0 web api文件上传

    第一部分: http://www.cnblogs.com/cgzl/p/8478993.html 第二部分: http://www.cnblogs.com/cgzl/p/8481825.html 第三 ...

  10. 【BZOJ4816】数字表格(莫比乌斯反演)

    [BZOJ4816]数字表格(莫比乌斯反演) 题面 BZOJ 求 \[\prod_{i=1}^n\prod_{j=1}^mf[gcd(i,j)]\] 题解 忽然不知道这个要怎么表示... 就写成这样吧 ...