Coding style &引用;“双”字;任务-应该避免吗?

Coding style &引用;“双”字;任务-应该避免吗?,coding-style,Coding Style,考虑到你有这样的表情 i = j = 0 假设这在您选择的语言中定义良好。一般来说,把它分成两个表达式会更好吗 i = 0 j = 0 我有时在库代码中看到这一点。在简洁性方面,它似乎并没有给您带来什么好处,而且它的性能也不应该比这两个语句更好(尽管这可能取决于编译器)。那么,有没有理由使用一个而不是另一个呢?还是只是个人喜好?我知道这听起来像是个愚蠢的问题,但它困扰了我很长一段时间:-)。第二种方法更具可读性和清晰性,我更喜欢它 但是,我尽量避免“双重”声明: int i, j; 而不是

考虑到你有这样的表情

i = j = 0
假设这在您选择的语言中定义良好。一般来说,把它分成两个表达式会更好吗

i = 0
j = 0

我有时在库代码中看到这一点。在简洁性方面,它似乎并没有给您带来什么好处,而且它的性能也不应该比这两个语句更好(尽管这可能取决于编译器)。那么,有没有理由使用一个而不是另一个呢?还是只是个人喜好?我知道这听起来像是个愚蠢的问题,但它困扰了我很长一段时间:-)。

第二种方法更具可读性和清晰性,我更喜欢它

但是,我尽量避免“双重”声明:

int i, j;
而不是

int i;
int j;

如果它们是连续的。特别是在MyVeryLong.和ComplexType的情况下,它取决于语言。在高度面向对象的语言中,双重赋值导致同一个对象被赋值给多个变量,因此一个变量中的变化反映在另一个变量中

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

大多数人会发现这两种可能性都同样可读。这些人中的一些人对这两种方式都有个人偏好。但有些人乍一看可能会对“双重任务”感到困惑。我个人喜欢单独的方法,因为

  • 它是100%可读的
  • 与双变量相比,它实际上并不冗长
  • 它让我忘记了=运算符的关联性规则

从前,存在性能差异,这是使用此类分配的原因之一。编译器将变成
i=0;j=0到:

load 0
store [i]
load 0
store [j]
因此,您可以使用
i=j=0
保存指令,因为编译器会将其转换为:

load 0
store [j]
store [i]
如今,编译器可以自己进行这种类型的优化。此外,由于当前的CPU一次运行多条指令,性能不能再简单地用指令数来衡量。一个操作不依赖于另一个操作的结果的指令可以并行运行,因此为每个变量使用单独值的版本实际上可能更快

关于编程风格,您应该使用最能表达代码意图的方式


例如,当您只想清除某些变量时,可以将赋值链接起来,当值具有特定含义时,可以将其作为单独的赋值。特别是如果将一个变量设置为值与将另一个变量设置为相同值的含义不同。

这两种形式反映了对赋值的不同观点

第一种情况将赋值(至少内部赋值)视为运算符(返回值的函数)

第二种情况将赋值视为语句(执行某项操作的命令)

在某些情况下,作为运算符的赋值有其意义,主要是为了简洁,或用于预期结果的上下文。但是我觉得很困惑。有几个原因:

  • 赋值运算符基本上都是副作用运算符,现在编译器需要对其进行优化。在C语言和C++语言中,它们会导致许多未定义的行为情况,或未优化的代码。
  • 目前还不清楚它应该归还什么。赋值运算符应返回已赋值的值,还是应返回其存储位置的地址。一个或另一个可能有用,取决于上下文
  • 对于像
    +=
    这样的复合赋值,情况甚至更糟。目前尚不清楚操作员是否应返回初始值、组合结果,甚至返回其存储位置
作为语句的赋值有时会导致中间变量,但这是我看到的唯一缺点。很明显,编译器知道如何有效地优化这些语句

基本上,只要可能,我都会避免被指派为操作员。所提出的案例非常简单,并不令人困惑,但作为一般规则,我仍然更愿意这样做

i = 0
j = 0


对于支持并行赋值的语言。

首先,在语义级别上,这取决于您是想说
i
j
是相同的值,还是恰好两者都有相同的值

例如,如果
i
j
是二维数组中的索引,则它们都从零开始
j=i=0
表示
i
从零开始,而
j
i
开始的地方开始。如果你想从第二行开始,你不一定要从第二列开始,所以我不会在同一个语句中初始化它们——行和列的索引恰好都从零开始

此外,在
i
j
表示复杂对象而不是整数变量的语言中,或者赋值可能导致隐式转换的语言中,它们不是等价的:

#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'
                  ;
    }

}
#包括
类复杂对象
{
公众:
常量复杂对象和运算符=(常量复杂对象和其他){

std::更不用说
char*i,j;
char*i,*j;
@Ignacio:与您的主题相关的好问题@kris:但问题并不是问这个语法。我指出,一行组合赋值的等价物不是将同一常数赋值给两个对象。这依赖于约定t赋值的结果是分配给第一个变量的值。这是一种可能的选择,而不是许多。在支持赋值时隐式强制转换的语言(如C++)中,执行强制转换之前或之后返回的值是否应该是对象甚至不明显(我相信这是第一个,但必须在标准参考文件中进行检查才能确定)。
#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'
                  ;
    }

}