调用 cmath 函数时应该使用 std:: 吗?

Ale*_*ues 4 c++ assembly std cmath

这是一个由两部分组成的问题:

如果我#include <cmath>在标题中, 1 - 使用,比如说,和
之间有什么区别? 2 - 为什么我得到的汇编代码与另一个的汇编代码如此不同?(产生的指令明显减少)std::log10()log10()
std::log10()

谢谢!

#include <cmath>

float using_std(float i) {
    return std::log10(i);
}

float not_using_std(float i) {
    return log10(i);
}
Run Code Online (Sandbox Code Playgroud)

组装(来自godbolt

using_std(float):
        jmp     log10f
not_using_std(float):
        sub     rsp, 8
        cvtss2sd        xmm0, xmm0
        call    log10
        add     rsp, 8
        cvtsd2ss        xmm0, xmm0
        ret
Run Code Online (Sandbox Code Playgroud)

我知道这些指令不是“实际”汇编,它们可能隐藏了更细粒度的指令,我只是想知道我看到的差异是否与代码的实际性能相关。

好吧,这是有道理的,如果我改为#include <math.h>,它们是相同的:

using_std(float):
        jmp     log10f
not_using_std(float):
        jmp     log10f
Run Code Online (Sandbox Code Playgroud)

use*_*522 7

是的,您应该包含<cmath>并使用std::. 这样,您就可以保证不同参数类型的数学函数的所有重载都会被考虑。

您看到的是std::log10(i)使用float的重载log10,而log10(i)使用double重载。

log10(i)如果您仅包含<cmath>并且未指定它将在全局命名空间范围中声明哪些重载,甚至不能保证它会起作用。

为了保证全局重载可用,您需要包含<math.h>,这保证使所有重载std::log10在全局命名空间范围内可用(但不一定在std::)。因此,仅包含该内容时,您不应使用std::.

该标准建议只有需要有效 ISO C 的源文件才应使用<math.h>标头,而其他 C++ 源文件也应使用<cmath>标头,因此也应使用std::. 请参阅当前草案中的support.c.headers.general 。

当你调用double重载时,因为你的参数类型和函数返回类型都是float,所以调用前后需要进行类型转换,这就是额外指令的来源。

  • @AlexRodrigues与我原来的答案相反,这实际上保证也能工作(https://eel.is/c++draft/support.c.headers#other-1),但我认为标准库时不是一个好的风格否则,函数始终是“std::”的成员。 (2认同)