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语句就只能在执行期执行。

 

相关文章推荐

java条件运算符

  • 2013年12月10日 16:49
  • 784B
  • 下载

利用条件运算符的嵌套

  • 2011年11月19日 22:41
  • 296B
  • 下载

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

本文主要涉及c++中常见的一些神奇的tricks。 1. 获得可变参数列表中最大类型的类型大小 2. tagged union 3. 模板的特化...

条件运算符用法

  • 2011年09月14日 11:55
  • 1KB
  • 下载

C/C++ tricks (1)

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

C++ Tips and Tricks

http://www.cnblogs.com/Martinium/p/cpp_tips_and_tricks.html 整理了下在C++工程代码中遇到的技巧与建议。 0x0...

C++ Coding Tricks Note

string转C风格char数组: string A = "1234"; char ch_a[5]; strcpy(ch_a, A.c_str());

第八周—1.1实现复数中的运算符重载

/* * 程序的版权和版本声明部分 * Copyright (c)2012, 烟台大学计算机学院学生 * All rightsreserved. * 文件名称: fun.cpp * 作 者:...
  • JNWSGH
  • JNWSGH
  • 2013年04月19日 15:29
  • 545

第08周:1.1运算符重载

/* * Copyright (c) 2014, 烟台大学计算机学院 * All rights reserved. * 作 者:王颖 * 完成日期:2014 年 4 月 14 日 * 版 本 号...

Oracle 条件运算符

比较运算符  >, >=. =:等于  !=, 逻辑运算符运算的优先顺序是NOT,AND,OR。如果要改变优先顺序,可以使用括号  逻辑运算符  AND:逻辑与,表示两个条件必须...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C++ Tricks 1.1 条件运算符(?:)
举报原因:
原因补充:

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