您的解决方案可能从教科书的角度来看使用标准库版本会更“规范”,但我认为评估结果是错误的。你的代码被拒绝没有真正好的、合理的原因。
这是一个典型的例子,某人在
形式上是正确的(按照教科书要求),但却执意以单一愚蠢的方式坚持认为只有唯一正确的解决方案,而无法接受其他解决方案并说出
"...但这里是最佳实践,你知道的"。
在技术上来说,说
"使用标准库,那就是它的用途,并且已经尽可能地优化了",是一种正确、实用的方法。虽然有时候
"尽可能地优化"这部分会因为标准对于某些算法和/或容器的限制而出现错误。
现在,撇开观点、最佳实践和信仰不谈。事实上,如果您比较这两个方法...
int main(int argc, char**)
{
40f360: 53 push %rbx
40f361: 48 83 ec 20 sub $0x20,%rsp
40f365: 89 cb mov %ecx,%ebx
40f367: e8 a4 be ff ff callq 40b210 <__main>
return std::abs(argc)
40f36c: 89 da mov %ebx,%edx
40f36e: 89 d8 mov %ebx,%eax
40f370: c1 fa 1f sar $0x1f,%edx
40f373: 31 d0 xor %edx,%eax
40f375: 29 d0 sub %edx,%eax
//}
int main(int argc, char**)
{
40f360: 53 push %rbx
40f361: 48 83 ec 20 sub $0x20,%rsp
40f365: 89 cb mov %ecx,%ebx
40f367: e8 a4 be ff ff callq 40b210 <__main>
return (argc > 0) ? argc : -argc
40f36c: 89 da mov %ebx,%edx
40f36e: 89 d8 mov %ebx,%eax
40f370: c1 fa 1f sar $0x1f,%edx
40f373: 31 d0 xor %edx,%eax
40f375: 29 d0 sub %edx,%eax
//}
......它们产生完全相同的指令。
但是,即使编译器使用比较后跟条件移动(在更复杂的“分支赋值”中可能会这样做,在min
/max
的情况下也会这样做),那么与位操作相比,这可能慢了一个CPU周期左右,因此,除非您这样做数百万次,否则说“不高效”这个说法是有点可疑的。
一次缓存未命中,您就会受到条件移动100倍的惩罚。
对于任何一种方法都有有效的支持和反对的论据,我不会详细讨论。我的观点是,因为如此微不足道的细节而将OP的解决方案拒之门外是相当狭隘的。
编辑:
(有趣的小知识)
我只是出于好玩,没有利润,在我的Linux Mint桌面上尝试了一下,该桌面使用了较旧版本的GCC(5.4与上面的7.1相比)。
由于我没有多想就包含了<cmath>
(嘿,像abs
这样的函数显然属于数学,不是吗!)而没有使用整数重载的<cstdlib>
,结果是...... 令人惊讶。调用库函数比单表达式包装程序要差得多。
现在,为了维护标准库,如果您包含<cstdlib>
,那么无论哪种情况下产生的输出都完全相同。
供参考,测试代码如下:
#ifdef DRY
#include <cmath>
int main(int argc, char**)
{
return std::abs(argc);
}
#else
int abs(int v) noexcept { return (v >= 0) ? v : -v; }
int main(int argc, char**)
{
return abs(argc);
}
#endif
...导致
4004f0: 89 fa mov %edi,%edx
4004f2: 89 f8 mov %edi,%eax
4004f4: c1 fa 1f sar $0x1f,%edx
4004f7: 31 d0 xor %edx,%eax
4004f9: 29 d0 sub %edx,%eax
4004fb: c3 retq
现在,很容易陷入不知不觉使用错误标准库函数的陷阱中(我自己演示了它是多么容易!)。而且所有这些都没有任何来自编译器的警告,比如“嘿,你知道吗,你正在对整数值使用双重重载(显然没有警告,这是有效的转换)”。
考虑到这一点,可能还有另一个“理由”解释为什么OP提供自己的一行代码并不是那么糟糕和错误的。毕竟,他也可能犯同样的错误。
for
循环过敏吗?为什么要写那个while
,而不是写更常用的for (int i = 0; i < l-1; i++) {
呢?(你还可以将l-1
的计算提出循环条件外)此外,使用ans += max(...)
会更符合良好的编程风格。 - Peter Cordesfor
循环和+=
之外,你应该养成使用++i
而不是后缀的习惯(虽然在这里没有关系),并且注意Stroustrup教授将指针修饰符与类型而不是变量放在一起:char* p
。这实际上是他原始书籍中介绍C++给公众的第一件事。哦,还有不要把某些东西命名为l
。即使它作为后缀在语言中使用,也选择大写字母以避免看起来模糊不清。 - JDługosz