【问题标题】:Use of assignment operators inside if condition in C++在 C++ 中的 if 条件中使用赋值运算符
【发布时间】:2018-08-14 17:43:44
【问题描述】:

如果我在 if 条件中使用赋值运算符或输出函数,为什么会将其视为“真”布尔值?

例如,我这样做

if(cout << "a"){cout << "c";}

或者

if(int x=7){cout << "c";}

甚至

if(6){cout << "c";}

输出确实是,在每种情况下都是 c 和 c 和 c。但是我们被告知,在 if 条件中,我们必须使用一个最终计算为布尔值的表达式,例如 1 或 0。

那么我缺少的信息是什么?

【问题讨论】:

  • 它不必是布尔值truefalse。它必须是 contextually convertible 才能布尔值。见en.cppreference.com/w/cpp/language/if
  • int x=7 不是分配。这是初始化。
  • @RichardCritten 考虑if (auto opt = something_returning_optional()) { ... }。那是有效的,并且已经有效了很长时间
  • @NathanOliver 谢谢 - 还是有点奇怪 if(int x=7; int y=0){x=x;y=y} 很好
  • @RichardCritten 啊,选择语句中 init-statement 的魔力 #C++17

标签: c++ syntax


【解决方案1】:

在每种情况下,表达式都被转换为布尔值。在您使用的三种情况下,此 bool 的值都是正确的(可能并不总是正确的)。

if(cout << "a"){cout << "c";}

在这种情况下,表达式:

   cout << "a"

如果找到operator&lt;&lt;(std::ostream&amp;, char const*)定义你会发现返回值是std::ostream&amp;。所以这将返回对cout 对象(std::ostream 类型)的引用。流对象有一个布尔转换方法explicit bool(),可用于将对象转换为布尔值。其结果取决于对象的状态(如果它处于不良(失败)状态,它将返回 false)。

因此,您在此处检查流上的最后一个操作是否有效。如果是,则打印“c”。这通常用于输入流以验证用户输入。

int val;
if (std::cin >> val) {
    if (std::cout << "A value was correctly read\n") {
        // Add response worked.
    }
    else
    {
        // Something bad happened to std::cout
    }
}

在其他情况下,您使用 int 变量。这些可以隐式转换为布尔值。如果该值不为零,则为真(否则为假)。

【讨论】:

    【解决方案2】:

    条件内的每个值(或布尔转换)都会给你真值,除非它等于 0。

    (6)            returns => 6              != 0            => true
    (x = 7)        returns => 7              != 0            => true
    (cout << "aa") returns => ostream object. 
                              bool context so calls `ostream::operator bool()`
                              If the stream is in good state => true
                              Otherwise                      => false
    

    在 c 中,您可以使用带有此声明的 NULL 看到它:

    #define NULL 0
    

    这意味着如果指针等于NULL,它将在布尔转换中返回 false。

    布尔表达式的 C++ 示例:

    int a, b, *c;
    char d;
    bool e;
    
    a = 0;
    b = 2;
    c = nullptr;
    
    e = a; // false
    e = b - 2; // false
    e = c; // false
    
    c = &a;
    e = c; // true
    e = b; // true
    e = a + 1; // true
    e = b ^ b; // false
    
    d = 0;
    e = d; // false
    d = '0';
    e = d; // true
    

    【讨论】:

    • 在 C++11 中,流转换为 bool,而不是 void*
    • nullptr 不会“返回 0”。事实上,它存在的全部目的是评估为0,因为这是宏NULL 的常见问题。
    • NULL 与问题有何关联?
    • @Slava OP 只看到了 true 案例。我还想展示false 案例。
    【解决方案3】:

    在您展示的所有情况下,您仍然提供了一个最终可转换为bool 的表达式。如果您查看std::cout&lt;&lt; operator 和类似的ostreams,您会看到它们都返回对同一流的引用。该流还定义了一个conversion to bool operator,它隐式在需要bool 的上下文中调用。如果流没有错误,此特定转换将返回 true。其次,int x=7是一个初始化,它返回x刚刚初始化的值; 7 在这种情况下。如果 C++ 中的 int 不为零,则可以将其隐式转换为 bool 为 true,这就是为什么在第二个和第三个示例中 76 都评估为 true。

    【讨论】:

    • 请注意这里没有调用赋值运算符。 if(int x=7){cout &lt;&lt; "c";}{ int x=7; if(x){cout &lt;&lt; "c";}} 的语法糖
    • 你能用基本的术语解释一下吗?我是计算机科学的新手,几乎只有一个星期。什么是流?
    • @AdityaAgarwal 我将从recommended C++ book 的开头开始学习基本的语言结构和类。作为学校的初学者,cout 的详细信息可能并不重要,但是当您感到舒适并感兴趣时,请阅读有关隐式转换和运算符重载的内容。
    • 一般来说,C++ 有很多隐藏的惊喜,如果你不小心,可能会困扰你的代码。良好的实践和坚持简洁的风格和惯例将使事情变得简单和可预测。
    猜你喜欢
    • 2011-03-11
    • 1970-01-01
    • 2013-07-28
    • 2018-06-09
    • 2013-03-16
    • 1970-01-01
    • 2011-09-18
    • 2021-01-24
    • 1970-01-01
    相关资源
    最近更新 更多