C/C++,在使用全局参数或传递参数之间进行选择

C/C++, choose between using global or passing argurment

本文关键字:参数 选择 行选 之间 全局 C++      更新时间:2023-10-16

假设函数f1调用f2f2调用f3,最后调用f5,它们各自向被调用者传递一个参数"arg",如下所示:

f1(arg, ...) -> f2(arg, ...) -> f3(arg, ...) -> f4(arg, ...) -> f5(arg, ...)

另一种方式,使用全局"arg",无需传递参数"arg),如:

int arg = 5;
f1(...) -> f2(...) -> f3(...) -> f4(...) -> f5(...)

哪一个更好?或者还有什么方法更有用?

添加参数"arg"可以使函数独立且可重新输入,这可能很好,例如在多线程应用程序中。当队列中任意两个函数之间的全局变量值发生变化时,为多个函数使用一个全局变量可能会导致错误,并且会得到意外的无效结果。

在一些体系结构上,包括x86-64(pdf中的完整规范),前几个参数在寄存器中传递。因此,如果您总是在参数列表的同一位置使用arg,并且在所有函数中都一致使用它,那么编译器可能会利用这一点,将其保留在适当的寄存器中。

几乎所有ABI都使用寄存器作为函数的返回值;在一些ABI(例如ARM)中,这与用于第一个参数的寄存器相同。但不是在x86-64上:eax用于返回值,rdircx(取决于平台)用于第一个参数。无论如何,处理寄存器远没有处理堆栈那么昂贵,而且处理堆栈也没有那么昂贵。

所以,就我个人而言,我不会担心开销。全球化会给你带来麻烦。

当传递几个参数时,我会提请注意这种情况。情况变得更糟:

f1(arg1, arg2, ...) -> f2(arg1, arg2, ...) -> f3(arg1, arg2, ...) -> f4(arg1, arg2, ...)

在这种情况下,定义一个结构并传递其引用是有意义的:

struct MyParams
{
    int arg1, arg2;
};
void f()
{
   MyParams prms = { ... };
   f1(prms, ...) -> f2(prms, ...) -> f3(prms, ...) -> f4(prms, ...)
}

我建议您避免使用任何全局变量。收益(如果有的话)不值得亏本。