为按引用传递的 c++ 函数提供引用类型参数

providing a reference-type argument for pass-by-reference c++ function

我有一个很无聊的问题。

我想,当你为 C++ 函数做按引用传递时,你实际上必须传递一个引用类型的参数(或参数?)。但是我在我正在学习的资源中看到,基本上在整个网络上,我错了。

那么,这两者之间的真正区别是什么?为什么它们都有效?

scenario_1

#include <iostream>

int sum(const int& a, const int& b)
{
    return (a + b);
}

int main()
{
    const int a1 {2};
    const int a2 {20};
    
    std::cout << sum(a1, a2) << "\n";
}

scenario_2

#include <iostream>

int sum(const int& a, const int& b)
{
    return (a + b);
}

int main()
{
    const int& a1 {2};
    const int& a2 {20};
    
    std::cout << sum(a1, a2) << "\n";
}

引用引用其他地方的对象实例。当您使用对对象的引用时,对该引用的所有使用就好像您在使用该原始对象一样。这允许一个 T& 引用另一个 T&,等等——但最终它必须从 某处 .[= 引用现有的 T 对象。 23=]

这回答了您问题中“为什么它有效”的部分; 因为引用只是引用实例本身。


你的另一个问题“这两者之间的真正区别是什么”的答案有点复杂。 const C++ 中的引用有点奇怪,因为它们能够延长临时对象的生命周期

C++ 中的所有对象都有生命周期。通常,一个对象的生命周期从它们被创建时开始,并在它们的作用域结束时结束——无论这只是一个表达式的全部部分,还是直到文字结束的 } 作用域。引用查看那个生命周期,但通常不会影响生命周期(这意味着返回一个临时引用,例如会产生一个悬挂引用 到一个不复存在的对象)。

另一方面,

const 引用将生命周期延长到封闭范围的长度。所以当你有:

const int& a1 {2};
const int& a2 {20};

您实际做的是创建两个 临时未命名对象,值为 220const int&延长这些变量的生命周期

这就像你做了类似的事情:

const int __unnamable_value_1 = 2;
const int __unnamable_value_2 = 20;

const int& a = __unnamable_value_1;
const int& b = __unnamable_value_2;

在大多数情况下,我建议不要考虑 C++ 的这种怪异之处。如果要创建命名值,请按值创建它(例如 const T)。如果要引用可能不在同一位置构造的对象,请使用引用 (const T&).

C++ 有一个冗长且有时令人困惑的规则列表,根据这些规则,一种类型的对象自动转换为其他相关类型的对象。

例如,您可能有一个将 const char * 作为参数的函数,例如:

size_t strlen(const char *);

尽管它的参数是 const char *,但您很有可能成功地将非常量 char 数组传递给此函数:

char buffer[256];

// Some code.

size_t l=strlen(buffer);

你关于参考文献的问题是完全一样的。可修改的左值可自动转换为对同一类型的 const 对象的引用。你不用担心,编译器会帮你完成。

还有许多其他规则。这可能是您第一次接触 C++ 的自动转换规则(或隐式转换规则)。这不会是你的最后一次。

So, what is the real difference between these two and why both of them work?

没有实际区别。两个版本之间存在一些迂腐的差异,但它们产生相同的逻辑结果。