C++中的条件运算符还能为我做什么?

6

在使用条件运算符时,我遇到了一个奇怪的编译错误。

a,bint 类型的变量,但以下表达式会导致编译错误。

(a>b)?( std::cout << a ) : ( b=MAX );
16 (b <unknown operator> 5)' 

(a>b)?( a=MAX ) : ( std::cout<<b );
16 (&std::cout)->std::basic_ostream<_CharT, _Traits>::operator<< [with _CharT = char, _Traits = std::char_traits<char>](b)' 

但这个表达方式很好,这很奇怪...
(a>b)?( std::cout << a ) : ( std::cout<<b );

我不知道是什么原因造成了这样的差异,也不知道编译错误代表什么。这是我的gcc信息:

Reading specs from ./../lib/gcc/mingw32/3.4.2/specs
Configured with: ../gcc/configure --with-gcc --with-gnu-ld --with-gnu-as --host=
mingw32 --target=mingw32 --prefix=/mingw --enable-threads --disable-nls --enable
-languages=c,c++,f77,ada,objc,java --disable-win32-registry --disable-shared --e
nable-sjlj-exceptions --enable-libgcj --disable-java-awt --without-x --enable-ja
va-gc=boehm --disable-libgcj-debug --enable-interpreter --enable-hash-synchroniz
ation --enable-libstdcxx-debug
Thread model: win32
gcc version 3.4.2 (mingw-special)`

1
将具有副作用的语句放在条件表达式中看起来很丑。为什么不使用传统的if语句呢? - Brennan Vincent
@Johannes:我把你的评论标记为无建设性的。为什么不写一下解释你为什么那么不喜欢这个问题,而不是简单粗暴地回复呢? - Brennan Vincent
@Brennan 我认为提问者非常清楚这一点。我试图通过编辑来修复它,但它仍然难以理解。我从未见过一个被称为函数的16,并且从未在C++中看到过<unknown operator>(这也不是GCC诊断)。如果您没有正确格式化您的问题,在SE上已经超过一年了,您至少需要以允许其他人格式化的格式说明它。这就是为什么我-1'ed。我删除了我的其他评论,因为我发现它实际上没有帮助。 - Johannes Schaub - litb
相关:https://dev59.com/11HTa4cB1Zd3GeqPUso7 - Alexandre C.
3个回答

14

条件运算符必须始终返回相同的类型。在你的第一个例子中,

(a > b) ? (std::cout << a) : (b = MAX);

第一个分支返回类型std::ostream,第二个分支返回b的类型(考虑到上下文,它可能是一个整数)。你的第二个示例:

(a > b) ? (std::cout << a) : (std::cout << b);

没有这样的问题,因为两个分支都返回相同类型的std::ostream。在任何情况下,使用一个简单的if-else语句处理这些条件可能更加清晰。条件运算符往往会影响可读性,并且通常只在有条件地向变量赋值时才有用:

int a = (a > b) ? a : b;
std::cout << a;

5
只是一点小意见(因为总体而言,您的答案比我的表达更好),但是 a?b:cbc 的类型规则要复杂一些。基本上,编译器必须能够将其中一个类型转换为另一个类型。所以你可以有 longint,或者 Base*Derived*(但不是 Derived1*Derived2*)。另外,其中一个表达式可以是 throw 表达式,在这种情况下,表达式的类型就是另一个类型。 - James Kanze
实际上,void *p = 0; (a > b) ? (std::cout << a) : (p = malloc(1)); 这样的语句是完全可以的。 - Johannes Schaub - litb
6
另一种修复方法是使用逗号运算符:(a > b) ? ((std::cout << a), a) : (b = MAX); 这种写法的优点是让代码更加晦涩难懂。 ;) - David Hammen
@James, Johannes:感谢你们明确指出可以相互转换的类型也是可以的。我应该在我的答案中提到这一点。我从未考虑过在条件运算符中使用throw表达式。从可读性的角度来看,这是一个可怕的想法,但绝对是一个有趣的小贴士,我之前没有考虑过。 - Michael Koval
1
@Michael 在条件表达式中使用 throw 到底是不是一个可怕的想法,这取决于上下文。例如,在构造函数的初始化器中非常有用(在那里你不能使用 if)。 - James Kanze

4

?: 是表达式(或子表达式)中的运算符。表达式具有类型。对于 (a > b) ? (std::cout << a) : (b = MAX),它的类型应该是什么?在 C++ 中,类型是静态计算的,编译器无法确定 std::cout << a (类型为 std::ostream&)和 b = MAX (类型为 int)的公共类型。


是的,关键在于“表达式具有类型”的部分。 - Thanh DK

2
C++中的条件运算符还可以为我做什么?
嗯,它会对第二个和第三个参数进行类型匹配,这可以作为从表达式中提取类型的一种非常有用的方式。如果想了解如何使用条件运算符的这个特性,请阅读这篇令人惊叹的文章

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接