【问题标题】:Why does call-by-value example not modify input parameter?为什么按值调用示例不修改输入参数?
【发布时间】:2012-06-13 03:40:47
【问题描述】:

在下面的按值调用示例中,我无法理解为什么这段代码没有将 5 的值更改为 6。

第 11 行调用了函数 changeValue,它的值是 6,所以我本以为应该输出 6,但仍然输出 5?

#include <iostream>
using namespace std;

void changeValue(int value);

int main()
{
  int value = 5;
  changeValue(value);

  cout << "The value is : " << value << "." << endl;

  return 0;
}

void changeValue(int value)
{
  value = 6;
}

// This doesn't change the value from 5 to 6. 5 is output?

【问题讨论】:

  • 您可以通过定义 main 之前的函数来避免很多愚蠢的工作,而不是在此处声明它们然后定义它们。自 2012 年起,不做无意义的多余事情的一般原则被称为 DRYDon't Repeat Yourself。只需将其应用于大多数事物。 ;-)

标签: c++ call


【解决方案1】:

我将这个答案作为另一种思考编写函数和按值传递参数的方式。

您也可以按以下方式编写此代码。即传值传参,修改函数中的本地副本,不改变原值,返回修改后的值。

int changeValue(int val)
{
  val = 6;
  return val;
}

int main()
{
int value = 5;

value = changeValue(value);

cout << "The value is : " << value << "." << endl;

return 0;
}

我并没有以任何方式表明我对您的程序的建议比通过引用更好。相反,它只是学习函数式编程语言 (Clojure) 的方式正在影响我的思维方式。

此外,在 Python 等语言中,您不能修改标量参数。您只能返回一个新值。所以我的回答更像是在 C/C++ 中以不同方式思考事物的练习。

【讨论】:

  • 我真的认为您应该详细说明为什么这是比通过引用传递更好的替代方案,并修复您的代码格式。但是,由于这是一个很好的答案,+1
【解决方案2】:

目前观察到的行为是因为按值传递意味着实际上将值的副本(具有值的新整数)传递给函数。

您必须通过引用传递。为此,changeValue 函数将如下所示:

void changeValue(int& value)

其余代码将保持不变。

通过引用传递变量意味着将main 中声明的相同int value 传递给changeValue 函数。

或者,您可以将指向value 的指针传递给changeValue 函数。但是,这也需要更改调用函数的方式。

int main()
{
    int value = 5;

    changeValue(&value);

    ...

    return 0;
}

void changeValue(int* value)
{
    *value = 6;
}

【讨论】:

    【解决方案3】:

    这是因为changeValue () 函数中的更改是本地的。当您可以changeValue (value) 时,main 中变量value 的内容被复制到函数的名为value(同名)的形式参数中。同名并不意味着两者相同。您在函数内部访问的值是您在主函数中的值的副本

    要更改,您需要通过引用或指针传递它

    void changeValue (int *val)
    {
      *val = 6;
    }
    

    在 main 中使用 changeValue (&amp;value) 调用

    之所以有效,是因为传递了 main 中变量 value 的地址,并且该地址值被复制到函数的 val 中。通过*val我们可以得到复制到val中的地址内容,其实就是main中value的内容。

    void changeValue (int &val)
    {
      val = 6;
    }
    

    【讨论】:

    • 我对传递指针的唯一问题是它让那些从 C 开始的人(比如我)天生想要free / delete 一切。
    • 你应该对free/delete内存做一些协议。例如修复功能的职责。有些函数只负责分配内存和释放,有些只负责分配,但释放的责任将在调用函数上。
    【解决方案4】:

    与:

    副本分配了6,但没有返回更改。

    如果你想改变值,你需要一些参考或指针:

    尝试使用如下方法签名:

    void changeValue(int& value)
    

    这可能会达到你的预期

    【讨论】:

      【解决方案5】:

      value 的值没有改变,因为你传递给函数的 int复制到函数的堆栈帧中,然后它被改变了,当函数退出副本被破坏。 main的stackframe中原来的并没有改变,因为它被复制到了changeValue

      如果您想更改它,您应该传递对int 的引用,例如void changeValue(int&amp; value),它表示该值不会复制到函数中,而只是传递原始值的别名。

      【讨论】:

        【解决方案6】:

        当您按值传递函数参数时,对象的副本会传递给函数,而不是原始对象。除非您明确指定函数的参数,否则始终在 C/C++ 中按值传递。

        你的功能:

        void changeValue(int value)
        

        按值接收参数,简而言之,main() 中的value 的副本被创建并传递给函数,函数对该值而不是main() 中的value 进行操作。

        如果你想修改原来的那么你需要使用引用传递

        void changeValue(int &value)
        

        现在将原始value 的引用(别名)传递给函数,函数对其进行操作,从而反映main() 中的更改。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-11-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-10-09
          相关资源
          最近更新 更多