C++ 在哪种情况下,如果(a=b)是个好主意?

C++ 在哪种情况下,如果(a=b)是个好主意?,c++,c,C++,C,可能重复: C++编译器通过您编写的警告让您知道 if( a = b ) { //... 这可能是个错误,你肯定想写 if( a == b ) { //... 但是,是否有这样一种情况,即警告应该被忽略,因为它是使用此“功能”的好方法? 我看不出任何代码清晰的原因,所以它是否有用 while ( (line = readNextLine()) != EOF) { processLine(); } 这当然是最简单的例子,很多时候这是有用的。首先要记住的是,(a=true)返回tru

可能重复:

C++编译器通过您编写的警告让您知道

if( a = b ) { //...
这可能是个错误,你肯定想写

if( a == b ) { //...
但是,是否有这样一种情况,即警告应该被忽略,因为它是使用此“功能”的好方法? 我看不出任何代码清晰的原因,所以它是否有用

while ( (line = readNextLine()) != EOF) {
    processLine();
}
这当然是最简单的例子,很多时候这是有用的。首先要记住的是,(a=true)返回true,就像(a=false)返回false一样。

两个可能的原因:

void some( int b ) {
    int a = 0;
    if(  a = b ) {
       // or do something with a
       // knowing that is not 0
    } 
    // b remains the same 
 }
if( NULL = b ) // won't compile because it is illegal
               // to assign a value to r-values.
  • 分配和检查

    =
    运算符(未重写时)通常返回其指定的值。这是为了允许诸如
    a=b=c=3
    之类的语句。在您的问题中,它还允许您执行以下操作:

    bool global;//a global variable
    
    //a function
    int foo(bool x){
    
       //assign the value of x to global
       //if x is equal to true, return 4
       if (global=x)
           return 4;
    
       //otherwise return 3
       return 3;
    }
    
    …相当于但短于:

    bool global;//a global variable
    
    //a function
    int foo(bool x){
    
       //assign the value of x to global
       global=x;
    
       //if x is equal to true, return 4
       if (global==true)
           return 4;
    
       //otherwise return 3
       return 3;
    }
    
    此外,还应注意(正如Billy ONeal在下面的注释中所述),
    =
    运算符的左参数实际上是一个具有指定类型的类,该类型可以强制(隐式转换)为bool时,这也可以起作用。换句话说,
    (a=b)
    将求值为
    true
    false
    ,前提是a属于可以强制为布尔值的类型

    因此,除了
    =
    的左手参数是一个对象而不是bool之外,以下情况与上述情况类似:

    #include <iostream>
    using namespace std;
    
    class Foo {
    public:
        operator bool (){ return true; }
        Foo(){}
    };
    
    int main(){
        Foo a;
        Foo b;
    
        if (a=b)
            cout<<"true";
        else
            cout<<"false";
    }
    
    //output: true 
    
    这里,
    a
    必须是一个对象,
    b
    必须是一个正确的类型,这是由
    =
    操作符覆盖
    a
    类型的对象定义的。要了解更多关于运算符重写的内容,请参阅维基百科文章,其中包含C++实例:


  • 直截了当地说,作为个人观点,我真的不认为这是一个好主意

    我的意思是,我知道使用这种语法可以避免在代码中增加一行,但我认为它会降低代码的可读性

    这种语法对于@Steven Schlansker建议的语法非常有用,但直接将其用作条件并不是一个好主意

    只要我的两分钱

    但是有没有一种情况是警告 应该被忽略,因为它是一个好的 如何使用此“功能”?我不明白 任何代码清晰的原因都是可能的 有没有一个案例说明它有用

    while ( (line = readNextLine()) != EOF) {
        processLine();
    }
    
    可以通过在指定周围加上括号来抑制警告。这在某种程度上澄清了程序员的意图。我见过的与(a=b)情况直接匹配的常见情况如下:

    if ( (a = expression_with_zero_for_failure) )
    {
        // do something with 'a' to avoid having to reevaluate
        // 'expression_with_zero_for_failure' (might be a function call, e.g.)
    }
    else if ( (a = expression2_with_zero_for_failure) )
    {
        // do something with 'a' to avoid having to reevaluate
        // 'expression2_with_zero_for_failure'
    }
    // etc.
    
    关于编写这种代码是否有用,足以证明初学者(有时甚至是专业人员在最坏的时刻)遇到C++时遇到的常见错误,这很难说。这是继承自C和Stroustrup的遗产,而其他一些对C++设计的贡献可能是完全不同的,更安全的路线,如果他们没有试图使C++与C兼容,那么就可以了。
    我个人认为这不值得。我在一个团队中工作,以前曾多次遇到此错误。我本来会赞成不允许它(至少需要括号或其他明确的语法,否则它被视为构建错误),以减轻遇到这些错误的负担。

    这是C语言基本特性的结果:

    赋值操作的值就是赋值本身

    您可以使用该“返回值”作为
    if()
    语句的条件,这是偶然的

    顺便说一句,这是同样的技巧,让这种疯狂的简洁:

    void strcpy(char *s, char *t)
    {
        while( *s++ = *t++ );
    }
    
    当然,当到达
    t
    中的null字符时,while将退出,但同时它将被复制到目标
    s
    字符串


    这是否是一个好主意,通常不是,因为它会降低代码可读性并容易出错。

    您可以使用它来测试函数是否返回任何错误

    if (error_no = some_function(...)) {
        //handle error
    }
    
    假设某个函数在出现错误时返回错误代码,否则返回零

    注意,这个答案是关于C++的(我在写了“C”)之前开始写这个答案。 然而,在阅读了延斯·古斯特德的评论后,我意识到这不是我第一次写这样的答案。事实上,这个问题是另一个问题的翻版,对此我给出了以下答案:

    所以,我会无耻地在这里引用我自己的话来补充一个重要信息:
    如果
    不是关于比较的。这是关于评估的

    这种差异非常重要,因为它意味着只要可以计算为布尔值,
    if
    的括号内就可以有任何内容。这是件好事

    现在,通过禁止所有其他操作员都有权使用的
    =
    来限制该语言是该语言的一个危险的例外,这种例外的使用还远远不能确定,而且其缺点确实很多

    对于那些不容易使用
    =
    打字错误的人,还有一些解决方案(请参见下面的备选方案…)

    问题是你把问题颠倒过来了。“if”表示法并不像在其他语言中那样比较两个值

    C/C++
    if
    指令等待任何将计算为布尔值或空/非空值的表达式。此表达式可以包括两个值的比较,和/或可能更复杂

    例如,您可以有:

    if(i >> 3)
    {
       std::cout << "i is less than 8" << std::endl
    }
    
    允许用户在if中声明并使用p。它是一种语法糖。。。但是很有趣。例如,假设有一个类似XML DOM的对象,其类型在运行时之前是未知的,您需要使用RTTI:

    void foo(Node * p_p)
    {
        if(BodyNode * p = dynamic_cast<BodyNode *>(p_p))
        {
            // this is a <body> node
        }
        else if(SpanNode * p = dynamic_cast<SpanNode *>(p_p))
        {
            // this is a <span> node
        }
        else if(DivNode * p = dynamic_cast<DivNode *>(p_p))
        {
            // this is a <div> node
        }
        // etc.
    }
    
    在C++中,你也可以做到这一点。我脑子里没有确切的代码(也没有确切的DDJ文章)
    void foo(Node * p_p)
    {
        if(BodyNode * p = dynamic_cast<BodyNode *>(p_p))
        {
            // this is a <body> node
        }
        else if(SpanNode * p = dynamic_cast<SpanNode *>(p_p))
        {
            // this is a <span> node
        }
        else if(DivNode * p = dynamic_cast<DivNode *>(p_p))
        {
            // this is a <div> node
        }
        // etc.
    }
    
    synchronized(p)
    {
       // Now, the Java code is synchronized using p as a mutex
    }
    
    #define synchronized(lock) \
       if (auto_lock lock_##__LINE__(lock))
    
    synchronized(p)
    {
       // Now, the C++ code is synchronized using p as a mutex
    }
    
    if( NULL = b ) // won't compile because it is illegal
                   // to assign a value to r-values.
    
    const T a ;
    
    // etc.
    
    if( a = b ) // Won't compile because it is illegal
                // to modify a constant object
    
    void foo()
    {
        // some code
    
        LOCK(mutex)
        {
           // some code protected by a mutex
        }
    
        FOREACH(char c, MyVectorOfChar)
        {
           // using c
        }
    }
    
    #define EQUALS ==
    #define ARE_EQUALS(lhs,rhs) (lhs == rhs)
    
    int main(int argc, char* argv[])
    {
       int a = 25 ;
       double b = 25 ;
    
       if(a EQUALS b)
          std::cout << "equals" << std::endl ;
       else
          std::cout << "NOT equals" << std::endl ;
    
       if(ARE_EQUALS(a, b))
          std::cout << "equals" << std::endl ;
       else
          std::cout << "NOT equals" << std::endl ;
    
       return 0 ;
    }
    
    if( (a = b) != 0 ) {
       ...
    }
    
    a = b;
    if( a != 0 ) {
       ...
    }
    
    do {
     ...
    } while (current = current->next);
    
    if ((fp = fopen("filename.txt", "wt")) != NULL) {
        // do something with fp
    }
    
    RegEx r; if(((r = new RegEx("\w*)).IsMatch()) { // ... do something here } else if((r = new RegEx("\d*")).IsMatch()) { // ... do something here } int i = 0; if((i = 1) == 1) { // 1 is equal to i that was assigned to a int value 1 } else { // ? }
    if (CComQIPtr<DerivedClassA> a = BaseClassPtr)
    {
    ...
    }
    else if (CComQIPtr<DerivedClassB> b = BaseClassPtr)
    {
    ...
    }