“Double” assignment - should it be avoided?

跟風遠走 提交于 2019-12-04 16:48:38

问题


Consider you have some expression like

i = j = 0

supposing this is well-defined in your language of choice. Would it generally be better to split this up into two expressions like

i = 0
j = 0

I see this sometimes in library code. It doesn't seem buy you much in terms of brevity and shouldn't perform any better than the two statements (though that may be compiler dependant). So, is there a reason to use one over the other? Or is it just personal preference? I know this sounds like a silly question but it's bugging me for a long time now :-).


回答1:


The two forms reflects different points of view on the assignment.

The first case treats assignment (at least the inner one) as an operator (a function returning a value).

The second case treats assignment as a statement (a command to do something).

There is some cases where the assignment as an operator has it's point, mostly for brevity, or to use in contexts that expect a result. However I feel it confusing. For several reasons:

  • Assignment operator are basically side effect operators, and nowadays it's a problem to optimize them for compilers. In languages like C and C++ they lead to many Undefined Behavior cases, or unoptimized code.
  • It is unclear what it should return. Should assignment operator return the value that as been assigned, or should it return the address of the place it has been stored. One or the other could be useful, depending on the context.
  • With composite assignments like +=, it's even worse. It is unclear if the operator should return the initial value, the combined result, or even the place it was stored to.

The assignment as a statement lead sometimes to intermediate variables, but that's the only drawback I see. It is clear and compilers know how to optimize efficiently successive such statements.

Basically, I would avoid assignment as operator whenever possible. The presented case is very simple and not really confusing, but as a general rule I would still prefer.

i = 0
j = 0

or

i, j = 0, 0

for languages that supports, parallel assignment.




回答2:


Once upon a time there was a performance difference, which is one of the reason that this kind of assignment was used. The compilers would turn i = 0; j = 0; into:

load 0
store [i]
load 0
store [j]

So you could save an instruction by using i = j = 0 as the compiler would turn this into:

load 0
store [j]
store [i]

Nowadays compilers can do this type of optimisations by themselves. Also, as the current CPUs run several instructions at once, performance can no longer simply be measured in number of instructions. Instructions where one action doesn't rely on the result of another can run in parallel, so the version that uses a separate value for each variable might actually be faster.

Regarding programming style, you should use the way that best expresses the intention of the code.

You can for example chain the assignments when you simply want to clear some variables, and make it separate assignments when the value has a specific meaning. Especially if the meaning of setting one variable to the value is different from setting the other variable to the same value.




回答3:


It depends on the language. In highly-object-oriented languages, double assignment results in the same object being assigned to multiple variables, so changes in one variable are reflected in the other.

$ python -c 'a = b = [] ; a.append(1) ; print b'
[1]



回答4:


Firstly, at a semantic level, it depends whether you want to say that i and j are the same value, or just happen to both have the same value.

For example, if i and j are the indexes into a 2D array, they both start at zero. j = i = 0 says i starts at zero, and j starts where i started. If you wanted to start at the second row, you wouldn't necessarily want to start at the second column, so I wouldn't initialise them both in the same statement - the indices for rows and columns independently happen to both start at zero.

Also, in languages where i and j represent complicated objects rather than integral variables, or where assignment may cause an implicit conversion, they are not equivalent:

#include <iostream>

class ComplicatedObject
{
public:
    const ComplicatedObject& operator= ( const ComplicatedObject& other ) {
        std::cout << "    ComplicatedObject::operator= ( const ComplicatedObject& )\n";
        return *this;
    }
    const ComplicatedObject& operator= ( int value ) {
        std::cout << "    ComplicatedObject::operator= ( int )\n";
        return *this;
    }

};

int main ()
{
    {
        // the functions called are not the same
        ComplicatedObject i;
        ComplicatedObject j;

        std::cout << "j = i = 0:\n";
        j = i = 0;

        std::cout << "i = 0; j = 0:\n";
        i = 0;
        j = 0;
    }

    {
        // the result of the first assignment is 
        // effected by implicit conversion 
        double j;
        int i;

        std::cout << "j = i = 0.1:\n";
        j = i = 0.1;

        std::cout << "    i == " << i << '\n'
                  << "    j == " << j << '\n'
                  ;

        std::cout << "i = 0.1; j = 0.1:\n";
        i = 0.1;
        j = 0.1;

        std::cout << "    i == " << i << '\n'
                  << "    j == " << j << '\n'
                  ;
    }

}



回答5:


Most of the people will find both possibilities equally readable. Some of these people will have a personal preference for either way. But there are people who might, at first glance, get confused by the "double assignment". I personally like the separate approach, bacause

  • It is 100% readable
  • It is not really verbose compared to the double variant
  • It allows me forget the rules of associativity for = operator



回答6:


The second way is more readable and clear, I prefer it.

However I try to avoid "double" declaration:

int i, j;

instead of

int i;
int j;

if they're going consecutively. Especially in case of MyVeryLong.AndComplexType



来源:https://stackoverflow.com/questions/4172223/double-assignment-should-it-be-avoided

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!