C++传递参数是按引用还是按值?

4

我是一个编程新手,这里有一个关于引用传递的简单问题。在这个程序中,我正在计算二次方程的根。

void getCoefficients(double &a, double &b, double &c);
void solveQuadratic(double a, double b, double c, double &x1, double &x2);
void printRoots(double x1, double x2);

void error(string msg);

int main() {
        double a,b,c,x1,x2;
        getCoefficients(a,b,c);
        solveQuadratic(a,b,c,x1,x2);
        printRoots(x1,x2);
        return 0;
}

所以,我的问题是我似乎从主程序向getCoefficients和solveQuadratic传递了值,但在getCoefficients和solveQuadratic的函数定义中,我似乎接受引用作为参数,并且对于这是如何工作感到困惑?


传递引用可以让被调用的函数修改传入的变量(这与按值传递不同,后者只接收值的副本)。在您的情况下,并根据函数名称,我会假设 getCoefficients 填充 a、b、c,然后 solveQuadratic 按值接收这些系数并填充根 x1、x2,最后 printRoots 打印 x1、x2 的值。 - dxiv
它的工作原理:语法黑魔法。编译器看到函数需要使用引用调用,并生成适当的代码,使其在没有进一步用户干预的情况下发生。 - user4581301
我不认为这完全是与上面链接的问题重复。楼主对于在 main 中传递值/引用感到困惑。 - anukul
@AnukulSangwan 当“closer”被归属于社区时,这意味着提问者自己批准了重复问题。 - Jeffrey Bosboom
抱歉,我是根据问题中的内容进行评论的。我的问题是,我似乎从主程序传递值到getCoefficients和solveQuadratic函数定义中,但在这些函数定义中,我似乎接受引用作为参数,并且对此感到困惑,不知道它是如何工作的? - anukul
4个回答

4

当通过引用传递变量时,您在函数中对其所做的任何更改都会反映在调用函数中。

另一方面,当您通过值传递变量时,对其所做的更改是局部的,因此不会反映在调用函数中。

例如,

#include "iostream"
using namespace std;

void function1(int &x, int y) // x passed by reference
{
    x+=y;
}

void function2(int x, int y) // x passed by value
{
    x+=y;
}

int main()
{
    int x=10;
    function1(x, 10);  // x is passed by reference (no & while calling)
    cout << x << endl; // 20
    function2(x, 1000);// x is passed by value
    cout << x << endl; // 20
}

请注意,不论您在调用function2时传入哪个值作为y参数,都不会对第二个cout语句产生影响。

main函数中,您不决定是传值还是传引用。这由函数定义为您决定。无论是按值传递还是按引用传递,调用函数的格式都保持不变。


建议重新表述最后一段的第一句话:“在调用函数时,您无法决定是传递值还是引用。被调用函数的定义会为您决定。”通过消除对“main”的错误依赖,概括了答案。 - user4581301
感谢您详细的回复。我能够理解,通过引用传递值可以反映对调用函数的更改,并且为什么x两次都是20。但是,我仍然不明白为什么您不在主函数中使用function1(&x,10)? - tacqy2
@tacqy2,你不需要使用&,因为它不是一个指针。它是一个引用,并且不需要将地址传递给被调用的函数。 - Paul Rooney
1
@Ankul Sangwan这句话“另一方面,当你通过值传递变量时(不使用&),”有点令人困惑。不清楚你打算在何时何地使用&,可能是导致问题的原因。是在函数定义中(将参数标记为引用)还是在调用函数时(作为传入变量的地址)。 - Paul Rooney
@PaulRooney 是的,那正是我的困惑!! - tacqy2
显示剩余3条评论

1

void getCoefficients(double &a, double &b, double &c);

这个函数接受三个参数,都是double &类型(指向double的引用)。引用和指针经常容易混淆,建议您先阅读一下此处的解释

我们将在主方法中称呼a、b、cmain_method_vars

当您调用getCoefficients时,该函数对传入其中的变量所做的任何操作都会反映在main_method_vars上。实际上,该方法是与main_method_vars一起工作的。

如果您使用的是void getCoefficients(double a, double b, double c),这意味着每次您使用main_method_vars调用此方法时,该方法将复制a、b、c的值并使用新副本而不是使用原始副本。


0
void getCoefficients(double &a, double &b, double &c);
void solveQuadratic(double a, double b, double c, double &x1, double &x2);

例如,函数 getCoefficients 中的变量 a、b、c 是通过引用传递的,因此如果它们在 getCoefficients 函数中的值发生了改变,那么在主函数中它们的值也会被改变。

0

虽然不是直接的答案,但您可以查看“变量作用域”主题。它将解释为什么在不同的函数中,“a”,“b”和“c”这些符号可能代表相同的东西或不代表相同的东西。了解局部变量的概念是理解“按值传递”、“按指针传递”和“按引用传递”的先决条件。

您还可以进行第一个测试:尝试更改其中一个函数的参数名称,例如getCoefficients(double &first,double&second,double &third)

您还可以进行第二个测试:尝试调用solveQuadratic(10, 20, 30, x1,x2)getCoefficients(1,-2,1)。第一个应该可以工作,但第二个不行。

最后,您可以尝试进行第三个测试:更改printRoots函数中参数x1和x2的值。然后检查这些更改是否也发生在主函数中(当然是在调用printRoot之后)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接