假设我有一个重复数百万次的循环。在这个循环里面我有一个函数调用。
在这个函数内部,我需要对一开始创建的一些临时变量进行操作。现在,哪一个更好:
a)在代码的开头创建临时变量,在循环开始时将其初始化,并将其作为函数参数传递给
b)在被调用函数的开头创建本地临时变量?
这是一个有问题吗?我想知道哪一点被认为是更好的实践,哪一点更快。
答案 0 :(得分:9)
让我们假设some_function()
的一些可能的定义,你将从你的循环调用的函数。
// Method 1
void some_function() {
int temporary;
// Use temporary
}
// Method 2
void some_function(int temporary) {
// Use temporary
}
// Method 3
void some_function(int *temporary) {
// Use *temporary
}
方法1可能是这些选项中最具可读性的,所以除非你有真的做其他事情的理由,否则它是我更喜欢的。它也可能比其他任何一个都快,除非你的编译器正在内联函数调用。如果是,则所有三个都可能执行完全相同(如果编译器无法优化指针解引用,方法3可能仍然会更慢)。
如果编译器没有内联,那么方法2可能比方法1慢。这是因为,就堆栈分配的内存而言,它们是相同的 - 函数参数将存储在堆栈中当地人也是这样。函数参数和此上下文中的局部唯一区别在于函数参数可以由调用者赋予值。将值从调用者传递给函数的步骤(理论上)会减慢调用速度。
方法3几乎肯定会变慢,因为对临时内存的访问将包含一个间接级别。与访问本地相比,取消引用指针并不是一种便宜的操作。
当然,如果性能绝对至关重要,那么您应该对这些方法进行基准测试。我怀疑方法1会变得最快(或者至少不比其他方法慢),而且对我来说似乎更具可读性。
答案 1 :(得分:1)
如果函数外部不需要变量,那么它应该在函数内部。这允许编译器最好地优化代码,并使代码最易读和易于使用(这通常适用于“声明具有最小可能范围的变量”,尽管对于小函数,声明少数每次函数顶部的变量是最佳选项)。
从性能角度来看,将变量传递给函数要么等效,要么比拥有局部变量更糟糕。 [当然,编译器可能会内联所有内容,并且在这两种情况下最终会得到完全相同的代码,但这取决于编译器和您拥有的代码]。
正如其他人所提到的,将指针传递给局部变量将导致访问指针以获取值的“惩罚”。它可能没有太大的区别,但它几乎肯定会产生一些不同。这绝对是最后的选择。 [注意,如果变量是LARGE,则将副本传递给函数的开销可能仍然比指针的开销更差。但是如果我们假设它是一个简单的类型,如int
或float
,那么指针有明显的开销]。
如果对性能有任何疑问,您一定要对您的代码进行基准测试。如果在排序算法或类似的算法之间做出选择,那么在互联网上询问其他人可能是值得的,但如果在一些更微妙的差异中这是“更好地做这个或那个”的情况,那么差异往往是小而你的特定编译器所做的将比“理论上更好”具有更大的影响力。
答案 2 :(得分:0)
如果将变量作为指针而不是值传递,则这两种方法之间存在细微差别。指针将被推送到调用堆栈,并且必须被引用才能获取/设置值。
相反,将其设置为本地值或按值传递将把值放在堆栈上。在这种情况下,重要的不是它是局部值还是传递值...尽管有一个可能的警告,基于在传递值的情况下如何在函数之外处理变量...如果它存储在一个变量(不传递文字值)然后它必须从内存中获取并推送到堆栈上。如果它是从函数内部的文字值设置的,那么它只是一个文字推入堆栈并保存了一个内存周期。
您省略的第三个选项是使用全局变量。
在值不变的情况下,值始终是,然后最佳答案使用#define并将其直接编译为代码作为文字。