【问题标题】:Why in conditional operator (?:), second and third operands must have the same type?为什么在条件运算符 (?:) 中,第二个和第三个操作数必须具有相同的类型?
【发布时间】:2012-03-28 13:12:43
【问题描述】:

为什么在条件运算符(?:)中,第二个和第三个操作数的类型必须相同?

我的代码是这样的:

#include <iostream>
using std::cout;

int main()
{
    int a=2, b=3;
    cout << ( a>b ? "a is greater\n" : b );  /* expression ONE */
    a>b? "a is greater\n" : b;               /* expression TWO */

    return 0;
}

使用g++编译时报错:

main.cpp:7:36: error: operands to ?: have different types ‘const char*’ and ‘int’
main.cpp:8:28: error: operands to ?: have different types ‘const char*’ and ‘int’

我想知道为什么它们必须具有相同的类型?

(1) 在我看来,如果(a&gt;b) 为真,那么表达式( a&gt;b ? "a is greater\n" : b ) 将返回"a is greater\n"cout &lt;&lt; "a is greater\n" 将输出该字符串;
否则表达式将返回bcout &lt;&lt; b 将输出b的值。

但是,不幸的是,它不是这样的。为什么?

(2) 第二个表达式得到同样的错误。

PS:我知道,是标准说一定要这样,但是,为什么标准这么说呢?

【问题讨论】:

  • 请注意,它们不一定必须具有完全相同的类型;可以进行一些转化,但允许的转化次数很少,以避免意外行为。

标签: c++ c operator-keyword


【解决方案1】:

我想知道为什么它们必须具有相同的类型?

在 C++ 中,任何表达式都必须具有单一类型,并且编译器应该能够在编译时推导出它。

这源于 C++ 是一种静态类型语言,其中所有类型必须在编译时已知。

【讨论】:

    【解决方案2】:

    你应该试着分解正在发生的事情来理解:

    cout << ( a>b ? "a is greater\n" : b );
    

    这转化为:

    operator<<(cout, ( a>b ? "a is greater\n" : b ));
    

    在那个阶段,编译器必须选择以下重载之一:

    ostream& operator<<(ostream&, int);
    ostream& operator<<(ostream&, const char*);
    

    但它不能,因为三元运算符的结果类型尚不知道(仅在运行时)。

    为了让事情更清楚,这样想:

     auto c = a>b ? "test" : 0;
    

    c 的类型是什么?它不能在编译时决定。 C++ 是一种静态类型语言。所有类型必须在编译时已知。

    编辑:

    你对a ? b : c的看法如下:

    if (a)
        b;
    else
        c;
    

    其实是这样的:

    if (a)
        return b;
    else
        return c;
    

    【讨论】:

    • 谢谢,但是第二个表达式呢?我不打算将它分配给其他任何人。 @J.N.
    • @UniMouS 你没有分配给其他人,但你可以。三元运算符被定义为返回一个值。你只是忽略它,但它就在那里。
    • @UniMouS,如果您将第二个表达式写为a&gt;b? (void)"a is greater\n" : (void)b;,即如果您告诉编译器丢弃子表达式的值,您的第二个表达式将起作用。
    • 'auto c = a>b ? “测试”:0;'可能不是一个很好的例子。因为常量 0 可以用作 NULL 指针来分配给任何类型的指针,'a>b ? "test" : 0' 有效,其类型为 'char*'(或 C++ 中的 'const char*')。
    【解决方案3】:

    它是一种强类型语言,需要将整个 ?: 视为变量或语句,例如:

    int i = 3;
    int j = 5;
    int k = (2 > 1 ? i : j) + 3;
    

    在这种情况下,如果 i 是一个字符串,你希望它应该为你做什么?

    【讨论】:

      【解决方案4】:

      它们实际上不必是同一类型。例如,像int a = argc &gt; 1 ? 2 : 'a'; 这样的表达式是完全允许的,即使2 的类型是int,而'a' 的类型是char

      但确实必须隐式转换为相同的类型。原因很简单:运算符必须产生 one 值,并且编译器必须能够确定该值的类型。如果两种类型之间没有隐式转换,则表达式不会产生一种类型。

      【讨论】:

      • 如果有隐式转换,那不就意味着它们最终相同的类型吗?
      • @osirisgothra:结果类型从任何一条腿都是一样的,是的。
      【解决方案5】:

      ?: 表达式将产生一个值(称为 rvalue),该值将分配给一个变量(称为 lvalue),如 J.N.提到,C++ 是一种静态类型语言,lvalue 必须在编译时知道。

      int num = a>b ? a : "eh, string?";
      

      上面的代码无法编译,因为变量num只能容纳一个int,不允许使用字符串。

      【讨论】:

        猜你喜欢
        • 2012-09-23
        • 2016-04-13
        • 2013-09-11
        • 1970-01-01
        • 1970-01-01
        • 2018-01-06
        • 2017-04-23
        • 2015-03-15
        • 1970-01-01
        相关资源
        最近更新 更多