布尔表达式是否像if或switch一样繁琐?

时间:2019-04-04 00:14:06

标签: c++

为了代码紧凑,通常我将一些temp_file = NamedTemporaryFile(delete=False) with open('clientlist.csv','rb') as csvfile, temp_file: reader = csv.DictReader(csvfile) fieldnames = ['Account Name','Account Number','Date Last Checked'] writer = csv.DictWriter(temp_file, fieldnames=fieldnames) writer.writeheader() print(temp_file.name) for row in reader: writer.writerow({ 'Account Name': row['Account Name'], 'Account Number': row['Account Number'], 'Date Last Checked': row['Date Last Checked'], }) #shutil.move(temp_file.name, client_list) 语句转换为布尔表达式。例如,如果我有类似的东西

if

我会这样做的

foo(int x)
{
   if (x > 5) return 100 + 5;

   return 100;
}

这很简单,所以没问题,问题是当我有多个测试时,我可以大大简化它们(以可读性为代价,但这是另一个问题)。

所以问题是foo(int x) { return 100 + (x > 5) * 5; } 评估是否像显式分支一样繁重。

3 个答案:

答案 0 :(得分:3)

在两种情况下,如果表达式u = u.reshape((-1, 1)).T 的计算结果为(x > 5),则必须对其进行检查。并且如前所述,即使未启用任何优化,两个版本都可以编译为same assembly

但是,《 C ++核心准则》的Philosophy section具有这两个规则,您最好注意以下几点:

  • P.1:直接在代码中表达想法
  • P.3:表达意图

尽管这些规则无论如何都无法执行,但遵守这些规则将使您采用带有true语句的版本。

这样做可以减少那些几个月后甚至需要自己维护代码的人的负担。

答案 1 :(得分:1)

您似乎正在将C ++语言构造与程序集中的模式进行混合。考虑到八十年代末或九十年代初的编译器,对这一级别的代码进行推理可能是可行的。然而,在这一点上,编译器进行了许多优化和转换,其正确性或实用性甚至对于普通程序员而言都不是很明显。一个非常简单的示例是常见的初学者错误,即假定以下等效项:

std::uint16_t a = ...;
a *= 2;   // a multiplication in assembly
a *= 17;  // ditto
a /= 3;   // a division in assembly

然后他们可能会惊讶地发现,他们选择的编译器将它们转换为等效的汇编程序,例如:

a <<= 1u;
a = (a << 4u) + a; // or even (a << 4u) | a if a < 16
a *= 43691u;

请注意,仅当已知a是除数的倍数时才允许进行最后的转换,因此您可能不会经常看到这种优化。它甚至如何工作?用数学术语来说,uint16_t可以看作是残基类环Z /(2 ^ 16)Z,并且在该环中,对任何互质为2 ^ 16的元素都存在一个乘法逆(即被2整除。如果d(例如3)与2互质,则它具有这样的逆,然后除以d就等于乘以d if的逆。 em>余数已知为零。 (我不会在这里讨论如何计算该逆数。)

这是另一个令人惊讶的优化方法:

long arithsum(long n)
{
    long result = 0;
    for (long i=0; i<=n; ++i)
        result += i;
    return result;
}

带有-O3的GCC相当平凡地将其转换为展开的附加循环。但是,如果您执行此操作,则我的Clang版本(9.0.0svn-something)会在您身上pull a Gauss,并将其翻译为:

long arithsum(long n)
{
    return (n * (n+1)) >> 1;
}

无论如何,同样的警告适用于if / switch等。尽管这些是控制流结构,所以您认为它们与分支相对应,但事实并非如此。同样,如果编译器具有优化规则(根据该优化规则看似有益),或者即使无法将其自身的AST或中间表示形式转换为机器代码而又没有优化规则,则看似非分支操作也可以转换为分支操作。使用分支(在给定的体系结构上)。

TL; DR:在试图超越编译器之前,首先要弄清楚编译器为直接/可读代码生成的程序集。如果此汇编程序很好,那么使代码更微妙/更不易理解就没有意义了。

答案 2 :(得分:0)

假设繁琐,您的意思是1/0。可以肯定的是,由于隐式类型转换,它可能在C / C ++中有效,但可能不适用于其他语言。如果那是您想要实现的目标,那么为什么不使用三元运算符(? :)也可以使代码更具可读性

foo(int x) {
   return (x > 5) ? (100 + 5) : 100;
}

也请阅读此stackoverflow文章-bool to int conversion