哪个更快?按引用传递与按值传递 C++

我认为通过引用传递应该比通过值传递更快,因为计算机不会复制数据,它只是指向数据的地址.

I thought that pass by reference should be faster then pass by value because the computer isn't copying data, it just points to the address of data.

但是,请考虑以下 C++ 代码:

But, consider the following C++ code:

#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;
}

现在这段代码只是一个普通的程序,它通过输入三角形的所需行和位置来递归计算帕斯卡数.

Now this code is just a normal program that compute pascal number recursively by entering the desired row and position of the triangle.

我尝试放置第 50 行和第 7 行,它计算大约 1 秒(按值传递).输出大约是 1300 万,这是正确的.所以我认为如果我通过引用传递它可能会更快,因为它不需要复制大量数据.但这是非常错误的,我不知道为什么需要更长的时间,大约是传递值所需的时间的 3 倍.问题是……

I tried putting row 50 and position 7 and it computes around 1 second (pass by value). The output is about 13 million which is correct. So I thought that it could be faster if I pass by reference instead because it doesn't need to copy a lot of data. But this is very wrong and I don't know why it took longer time about 3 times the amount it took for passing by value. The question is ...

为什么这个程序在我尝试将其更改为通过常量引用后计算如此缓慢?

因为递归函数是一个例外,你应该通过值而不是常量引用传递,这有关系吗?

Does it matter that because recursive function is an exception that you should pass by value rather than const reference?

推荐答案

哪个更快"的答案通常是这取决于".

The answer to "Which is faster" is usually "It depends".

如果不是传递 4 个字节的数据,而是传递一个指向数据的 8 个字节的指针,那么您真的不能指望这会让事情变得更快.如果不是传递 100 个字节的数据,而是传递一个指向数据的 8 个字节的指针,那就不同了.

If instead of passing four bytes of data you are passing an eight byte pointer to data, then you can't really expect that to make things faster. If instead of passing 100 bytes of data you are passing an eight byte pointer to data, that's different.

但是现在函数没有数据,它只有一个引用.所以每当它需要读取数据时,它必须通过引用间接地做到这一点.那需要更长的时间.如果您传递一个 100 字节的对象并且只读取其中的 8 个字节,您仍然有可能获胜.但是,如果您实际上读取了所有数据,并且可能多次读取,那么即使对于大对象,传递值也很容易更快.

But now the function doesn't have the data, it only has a reference. So whenever it needs to read the data, it has to do that indirectly through the reference. That takes longer. If you pass a 100 byte object and only read eight byte of it, you still are likely to win. But if you actually read all the data, and maybe multiple times, then it could easily be faster to pass the value even for large objects.

真正的区别在于您传递对象时,而按值传递意味着将调用或多或少复杂的构造函数.通过引用传递意味着没有构造函数.但是 int 无论如何都没有构造函数.

The real difference comes when you pass an object, and passing by value means a more or less complex constructor will be called. Passing by reference means no constructor. But int has no constructor anyway.

然后是优化.按值传递意味着编译器知道您的函数是唯一可以访问数据的函数.通过引用传递意味着数据可以在任何地方.如果你有两个 int&参数,我可以传递一些 int 两次.所以增加行可能增加位置.或者它可能不会.这会扼杀优化.

And then there is optimisation. Passing by value means the compiler knows your function is the only one with access to the data. Pass by reference means the data could be anywhere. If you have two int& parameters, I could pass the some int twice. So increasing row might increase pos. Or it might not. That kills optimisations.

然后是优化规则:衡量它".你测量了它,发现什么更快.有时事情会无缘无故地更快或更慢.

And then there is the rule of optimisation: "Measure it". You measured it and found what's faster. Sometimes things are faster or slower for no good reason whatsoever.

相关文章