鲲鹏社区首页
中文
注册
开发者
我要评分
获取效率
正确性
完整性
易理解
在线提单
论坛求助

除日志打印类等专用函数外,不使用带可变长参数列表的函数

【说明】 C/C++语言中,支持可变长参数列表的函数,但是除针对日志打印等专用函数外,其他类型函数不应采用这种过于灵活定义方式;应当根据函数实际功能,按需定义确定性的参数个数。

【原理】 对于可变长参数列表,需要采用vastart/vaarg/vaend的方式在程序栈上进行变长参数解析,相对固定长度参数列表而言,增加了参数解析的开销。在性能敏感流程中调用可变长参数的函数,可能造成性能恶化。同时,可变长参数列表的解析过程较复杂,实现层面还存在安全性风险(如实参类型无法通过编译器进行类型检查等),可能为程序运行时带来异常。综合考虑,除日志打印类函数外,不允许定义与使用带可变长参数列表的函数。另外,C++中存在形式上类似可变长参数列表的函数(如std::makeunique智能指针构造函数),实际上是通过模板推导的方式在编译期完成参数个数与类型确认,不存在运行期的变长参数解析,以及安全性风险,因此不在上述讨论的范围内。

【注意事项】 不涉及

【案例】

优化前
int32_t FuncAddWithInt32(uint32_t num, ...)
{
    int32_t sum = 0;
    va_list args;
    va_start(args, num);
    // 输入保护 省略
    for (int32_t index = 0; index < num; index++) {
        int32_t curr = va_arg(args, int32_t);
        // 越界保护 省略
        sum += curr;
    }
    va_end(args);
    return sum;
}

说明: FuncAddWithInt32函数用于实现若干int32_t类型的数据的累加,通过num参数来控制累加值的个数;按照当前的实现方式,函数内部变长个数的局部变量累加需要采用循环解析的方式确认,性能开销大。

优化后
int32_t FuncAddWith2ParamInt32(int32_t para1, int32_t para2)
{
    // 越界保护 省略
    return para1 + para2;
}

int32_t FuncAddWith3ParamInt32(int32_t para1, int32_t para2, int32_t para3)
{
    // 越界保护 省略
    return para1 + para2 + para3;
}

说明:针对业务场景中只需要用到2个或3个参数增加时,可以考虑将上述变长参数的函数优化为FuncAddWith2ParamInt32和FuncAddWith3ParamInt32函数,参数个数确定,效率更高。其中,针对C语言,需要注意不同参数个数的函数名可以有差异;针对C++语言,可以利用overload技术共享一个函数名。