C++ Tricks 1.1 条件运算符(?:)

原创 2007年09月16日 13:22:00

1.1  条件运算符(?:)

条件运算符(?:)C++中唯一的三目运算符(trinary operator),用于在表达式中作条件判断,通常可以替换if语句,与Visual Basic中的iif函数、Excel中的if函数有同样的作用。语法形式如下:

condition ? true_value : false_value

其中condition 条件是任何可以转换为bool类型的表达式,包括但不仅限于boolint、指针。与ifwhile的条件部分稍显不同的是,这里不能定义变量,否则会导致语法错误。

另外,条件语句会切实地控制执行流程,而不仅仅是控制返回值。也就是说,两个返回值表达式中永远只有一个会被求值,在表达式的执行顺序很重要时,这点尤为值得注意。比如:

int *pi=getInt();

int i=pi?*pi:0;

这里,只有当pi的值不为0时,它才会被提领(dereference)。这种语义保证了程序的正确性,因为提领一个空指针将导致致命的运行期错误(通常是非法操作的警告)。同时,正因为条件运算符控制运算流程的特点,使得它不能用类似iif的普通函数来模拟:

int iif(int con,int t,int f){if(c)return t;return f;}//试图模拟?:

…//in some function

int *pi=getInt();

int i=iif(pi,*pi,0);//Error!

这段代码会导致上文提到的致命运行期错误。C/C++标准规定,参数在被传递给函数之前求值,因此无论pi为何值,都会被提领。又因为函数传回一个空指针的情况比较少见,所以这样的错误在调试时很难被发现,一旦发生又势必造成重大灾难。这样的代码在实践中应尽量避免。

 

有时,条件运算符控制流程的特点会不知不觉影响我们的代码。在C时代,最大值MAX通常用宏实现:

#define MAX(a,b) ((a)>(b)?(a):(b))

需要用额外的括号将宏参数和宏本体保护起来,以免运算符优先级扰乱逻辑,这是宏丑陋的特点之一,这里暂且不提。矛盾在于,用具有副作用的表达式调用宏时,会出现问题:

int i=5,j=6;

int a=MAX(++i,++j);

代码的作者原意显然是想先将i,j分别递增,再将其中较大的一个赋给a。执行这段代码,当i=5,j=6时,a=8,知道为什么吗?通过宏展开,赋值语句成这样:

int a=(++i)>(++j)?(++i):(++j);//删除了多余括号

在判断之前,ij被分别自增一次,然后舍弃:之前的部分,j又被自增一次。执行之后,i=6,j=8

MAX的更正确更安全的实现,是利用模板将类型参数化。STL标准算法中就有一个这样的工具级模版函数std::max

 

条件运算符是表达式而不是语句,这使得它可以出现在任何需要表达式的地方,这扩大了它的适用范围。在那些语法上只能出现表达式而不能出现语句的地方(比如变量初始化),条件运算符有着不可替代的作用。

条件运算符优于if语句的另一个场合是“模板元编程”(TMP, Template MetaProgramming)。在TMP这个古怪奇异的编译期运算编程技术中,一切旧有的技术和法则被全线击破,我们所能仰仗的工具,只有模板特化(Specialization)typedefs、函数声明(无法调用它们)、以及编译期常量运算。已经有人很深入地论证过,仅有以上这些,就已经形成了一个“图灵完善”的计算机语言。我们可以用模板特化技术,来模拟条件分支,循环迭代等一系列复杂的语言结构。由于可以参与编译期常量运算,条件运算符在TMP世界中很自然地扮演起重要角色。

比如,给与类型T的一个变量t,我们想声明一个缓冲区存放t和一个int,缓冲区的大小不小于sizeof(T)也不小于sizeof(int),我们可以这样写:

char buffer[sizeof(T)>sizeof(int)? sizeof(T): sizeof(int)];

我们不能用一个if语句替换这个运算:

int i;

if(sizeof(T)>sizeof(int))i=sizeof(T);

else i=sizeof(int);

char buffer[i];//语法错误!

原因在于数组声明中的下标必须是一个编译期常量,而不是一个运行期的值,条件表达式的运算可以在编译期进行,if语句就只能在执行期执行。

 

C++学习006-条件运算符

这里我也理解的不咋的,大致意思应该就是根据运算符号 的优先级不同来解决的 条件运算符是其中一部分,而条件运算符具有右结合性,当一个表达式中出现多个条件运算符时,应该将位于最右边的问号与理他最近的冒...
  • z609932088
  • z609932088
  • 2016年08月12日 09:27
  • 281

C++基础——tricks,让人惊艳的那些代码

本文主要涉及c++中常见的一些神奇的tricks。 1. 获得可变参数列表中最大类型的类型大小 2. tagged union 3. 模板的特化...
  • lanchunhui
  • lanchunhui
  • 2015年11月02日 00:01
  • 1119

C++ 条件运算符(三目运算符)

在某些情况下,可以用条件运算符“ ? : ”来简化if语句。 基本格式 “ ? : ”是一个三元运算符,其构成的表达式格式为:       ? : 执行流程 条件运算符的执...
  • ikke2682
  • ikke2682
  • 2017年02月07日 13:13
  • 566

C/C++ tricks (1)

1、在VS2005中(可能之后的版本也是如此,没有具体考证),BOOL和bool是有区别的,BOOL的定义是“typedef int BOOL;”并非0或1了,虽然是个小问题,但也让我绕了不少弯。2、...
  • ice1020502
  • ice1020502
  • 2011年03月16日 17:20
  • 366

神经网络Tips 和Tricks

神经网络Tips 和Tricks
  • heyongluoyao8
  • heyongluoyao8
  • 2015年10月31日 22:32
  • 9904

C++ 条件运算符和条件表达式

条件运算符是C++中唯一一个三元运算符,要求有三个操作对象,条件表达式的一般形式为:表达式1?表达式2:表达式3条件运算符的执行顺序是,先求解表达式1,若为真则求解表达式2,此时表达式2的值作为整个条...
  • chaipp0607
  • chaipp0607
  • 2017年02月04日 11:41
  • 1911

Android UI开发第四十篇——ScrollTricks介绍

ScrollTricks是一个开源控件,实现了两个简单功能: 1、Quick Return:向上滑动时,View也向上滑动并且消失,当向下滑动时,View马上出现。例如Google Now的搜索功能...
  • xyz_lmn
  • xyz_lmn
  • 2014年03月19日 20:56
  • 9949

css tricks,画各种基本图形

今天看到一个css tricks的文章,感觉不转载都对不起自己: 图形包括基本的矩形、圆形、椭圆、三角形、多边形,也包括稍微复杂一点的爱心、钻石、阴阳八卦等。当然有一些需要用到CSS...
  • zeyu1021
  • zeyu1021
  • 2015年02月25日 10:35
  • 637

CSS Tricks

CSS Tricks一些CSS的小技巧1.如何准确的居中? 参考Quick CSS Trick: How To Center an Object Exactly In The Center.cent...
  • winfredzen
  • winfredzen
  • 2017年02月16日 08:53
  • 562

深度学习之常见tricks

本文主要给出了在实现网络或者调节代码过程使用的以及平时看一些文章记录下来的一些小技巧,主要针对卷积网络和图像处理。就个人感受,有些技巧还是非常有效的,而且通常可以通过看开源库的一些文档或者源代码来发掘...
  • qq_26898461
  • qq_26898461
  • 2016年01月07日 11:25
  • 1429
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C++ Tricks 1.1 条件运算符(?:)
举报原因:
原因补充:

(最多只允许输入30个字)