关于通过引用传递论点的澄清

时间:2019-01-16 08:25:11

标签: c++ reference

在阅读关于将对函数的引用作为参数传递的同时,我发现本文passing arguments by reference(及其所讨论的代码)指出:

void getSinCos(double degrees, double &sinOut, double &cosOut)
{
   //SOME PROCESSING WITH THE PARAMETERS
}
  

即使不打算使用更新的输出,调用者也必须传递参数以保留更新的输出。更重要的是,语法有点不自然,输入和输出参数都放在函数调用中。从调用方的角度来看,sin和cos并不是输出参数并将被更改,这并不明显。这可能是此方法中最危险的部分(因为它可能导致犯错误)。一些程序员和公司认为这是一个足够大的问题,建议不要以这种方式通过引用传递,而在混入和混入参数时(使用更清晰的语法指示参数是否可修改),建议使用按地址传递。

当定义的参数是非常量引用时,确保不能传递诸如参数 3 之类的临时变量或其他整数/双精度常量,但是如何修改输入变量和恢复输入变量呢?本文指出,在同一变量中输出(因为对原始变量进行了更改)会很麻烦吗?当我刚接触C ++时,有人可以指导我吗?

2 个答案:

答案 0 :(得分:4)

这是人们根本无法期望的。假设您有以下代码:

int x = 5;
foobar(x);

函数调用后x的值是什么?大多数人希望它仍然是5,因为除非有未定义的行为,否则按值传递时它不会改变。在C语言中,甚至没有引用传递,因此该值始终为5。现在在C ++中,突然有引用传递,而仅从该代码段中,您无法知道函数调用后x是否会更改。为此,您必须查看foobar的实际签名。

它本身并不是“危险的”,但是如果使用不当,可能会导致代码不清晰和误导。尤其是当您混合使用参数时,有些参数是out参数,有些参数则没有参数,而有些参数具有误导性。在您的示例中,参数名称包含out表示它们不在参数中,这是减轻这种危险的好样式。

将其与以下代码段from here进行对比,以解释按引用传递代码在C#中的状态:

void Method(ref int refArgument)
{
    refArgument = refArgument + 44;
}

int number = 1;
Method(ref number);
Console.WriteLine(number);
// Output: 45

在这里,您会立即看到它通过引用传递,因为它说ref number

答案 1 :(得分:3)

该文章没有提及“修改输入变量并在同一变量中恢复输出” ,它只是说不清楚该函数可以更改哪些参数致电:

int x{};
int y{};
foo(x, y); // can you guess which variable has changed?

关于地址传递的部分具有“更清晰的语法,指示参数是否可修改”,这是完全胡扯。它不仅遭受与引用传递相同的问题,而且还暗示着某些参数可能是可选的,并且可能是所有权转移

int x{};
int y{};
foo(&x, &y); // can you guess which variable has changed?
foo(nullptr, &y); // can you guess whether this is correct usage?
foo(&x, &y); // can you be sure that foo won't delete pointer to x?

为了安全起见,可以使用类似(const)引用的显式传递:

int x{};
int y{};
foo(::std::as_const(x), y); // alright, x should not be changed inside