我有一个函数,如果个别输入参数有大量的数字,该函数在程序期间也运行了数亿次。
如果我想优化这个函数,我应该创建一个包含所有输入参数的新数据结构,并通过引用将它传递给函数,而不是将每个参数单独传递给函数吗?或者这无关紧要,因为编译器足够聪明,能够以更有效的方式处理这个问题吗?
答案 0 :(得分:2)
通常,传递包含变量的数据结构要好得多。这不是很好看或使用:
void f(int a, int b, int c, int d, int e, int f)
{
// do stuff
}
这样更好:
void f(Params p)
{
// do stuff with p
}
您可能希望通过引用传递,因此编译器只能传递对象的引用,而不是复制整个数据结构。 作为一个真实的例子:
double distance(double x1, double y1, double z1, double x2, double y2, double z2)
{
double dx = x1 - x2;
double dy = y1 - y2;
double dz = z1 - z2;
return sqrt(dx*dx + dy*dy + dz*dz);
}
如果将我们的(x,y,z)封装到数据结构中会更好:
struct Point
{
double x;
double y;
double z;
};
double distance(const Point &p1, const Point &p2)
{
double dx = p1.x - p2.x;
double dy = p1.y - p2.y;
double dz = p1.z - p2.z;
return sqrt(dx*dx + dy*dy + dz*dz);
}
更清晰的代码,您可以获得额外的好处,它可以*表现更好(*取决于您的编译器在优化任一版本时的智能程度)。
显然,这可能会有很大差异,具体取决于您实际要完成的内容,但如果您在某个上下文中有多个(4+)变量具有相似的用法,那么将它传递给数据可能会更好结构
答案 1 :(得分:1)
参数大部分是不变的,还是大多数参数在每次调用时都会改变?如果您只能执行一次,则不希望多次评估参数。
请记住编译器对参数的作用。
它评估每一个并将其推入堆栈。然后输入函数,它通过堆栈中的偏移量引用那些参数。所以它基本上就像你将参数放入一个块并传递块一样。但是,如果您自己构建块,则可以重新使用旧值,并仅评估已知更改的值。
在任何情况下,您都必须查看函数内部相对于将参数传递给它所花费的时间。如果你在不知道总体时间跨度的情况下调用它10 ^ 8次就无关紧要了。这可能是每次通话10ns,或每次通话10ms。如果是后者,几乎所有的时间都花在了函数内部,所以你调用它可能没什么区别。