【发布时间】:2014-12-20 13:27:41
【问题描述】:
我认为通过引用传递应该比通过值传递更快,因为计算机不是在复制数据,它只是指向数据的地址。
但是,请考虑以下 C++ 代码:
#include <iostream>
#include <cassert>
#include <cmath>
using namespace std;
// do not use pass by reference& with this function, it will become so slow
unsigned long long computePascal(const unsigned int row, const unsigned int position) {
if (position == 1 || position == row)
return 1L;
unsigned long long left = computePascal(row-1, position-1);
unsigned long long right = computePascal(row-1, position);
unsigned long long sum = left + right;
return sum;
}
int main() {
int row, position;
cout << "Input row and position: ";
cin >> row >> position;
assert(position > 0 && position <= row);
unsigned long long pascalNumber = computePascal(row, position);
cout << pascalNumber << endl;
return 0;
}
现在这段代码只是一个普通程序,它通过输入三角形的所需行和位置递归地计算帕斯卡数。
我尝试放置第 50 行和第 7 位,它计算大约 1 秒(按值传递)。输出大约是 1300 万,这是正确的。所以我认为如果我通过引用传递它可能会更快,因为它不需要复制大量数据。但这是非常错误的,我不知道为什么它需要更长的时间,大约是传递价值所需的时间的 3 倍。 问题是……
为什么在我尝试将其更改为通过 const 引用传递后,该程序的计算速度如此之慢?
因为递归函数是一个例外,你应该通过值而不是 const 引用传递,这有关系吗?
【问题讨论】:
-
“不是在复制数据,它只是指向数据的地址”——如果数据小于地址,那么复制它可能比通过函数的地址。并且通过引用传递会增加一个间接级别,这是有代价的。
-
int* 类型至少与 int 本身一样大,因此您不会在复制时节省任何时间,并且必须在其之上执行几个地址和取消引用操作。
-
没有明确的规则哪一个更快。当整数通过值传递时,它们可以存储在寄存器中,速度非常快。由于这个原因,通常您应该按值传递基本数据类型。通常只有在复制类型的成本很大时才值得。
-
只是说:如果你的计算时间超过几微秒,你就做错了。我会说不恰当地使用递归。如果结果为 n,那么您正在拨打 n 次电话。
-
哦,我忘了认为地址大于数据本身。谢谢你的澄清。只需回答,我会将您标记为最佳答案并关闭线程。我从 learncpp.com 得到这个想法,您应该始终使用按 const 引用传递,而不是一直按值传递,因为不需要克隆数据。所以我认为现在这是错误的。但是这个问题有什么问题呢?因为我不知道所以我被否决了?还是这个问题对其他人来说太容易了?
标签: c++ recursion pass-by-reference pass-by-value pass-by-const-reference