通过引用调用 <math.h> 函数是否安全?

1 c++ math reference function

请告诉我通过以下方式调用数学函数是否安全:

map<string,double(*)<double> func_map = { {"sin", &std::sin } ... }
...
double arg = 2.9;
double res = func_map["sin"](arg);
Run Code Online (Sandbox Code Playgroud)

Ted*_*gmo 6

获取标准库中不在指定可寻址函数列表中的函数地址会导致未指定的行为(至少自 C++20 起)。std::sin而其他<cmath>函数不在该列表中,因此为了安全起见,请将它们包装在函子中,例如 lambda:

#include <cmath>
#include <map>
#include <string>

int main() {
    std::map<std::string, double(*)(double)> func_map = {
        {"sin", [](double x) { return std::sin(x); }},
        {"cos", [](double x) { return std::cos(x); }},
    };
}
Run Code Online (Sandbox Code Playgroud)

通过以下方式调用数学函数是否安全:

double res = func_map["sin"](arg);
Run Code Online (Sandbox Code Playgroud)

不,如果您要调用的函数不存在于 中func_map,则使用下标operator[]将首先将double(*)(double)指向插入nullptr到映射中,然后返回该函数nullptr。调用nullptr(arg)会导致未定义的行为。为了确保安全,您可以执行以下操作:

  • 制作func_map const。这可以防止您使用任何可能在映射中插入某些内容的函数,例如下标运算符。
  • 如果映射中不存在该函数,则用于func_map.at("sin")(arg);获取异常 ( )。std::out_of_range您可以安全地捕获它并向用户打印一条消息:
    double res = func_map["sin"](arg);
    
    Run Code Online (Sandbox Code Playgroud)
  • 如果您不希望未知函数出现异常,则可以使用成员函数find
    try {
        double res = func_map.at("sin")(arg);
        std::cout << res << '\n';
    } catch (const std::out_of_range& ex) {
        std::cout << "unknown function\n";
    }
    
    Run Code Online (Sandbox Code Playgroud)