C++ 为什么可以';我的函数不能访问并修改传递给它的变量吗?

C++ 为什么可以';我的函数不能访问并修改传递给它的变量吗?,c++,pointers,reference,C++,Pointers,Reference,我写了这个小程序来解释我的观点,变量a保持不变,它打印4。后来我知道我需要使用指针或引用;为什么呢 #include <iostream> void setToTen(int x) { x = 10; } int main(){ int a = 4; setToTen(a); std::cout << a << std::endl; } #包括 void setToTen(int x){x=10;} int main(){ I

我写了这个小程序来解释我的观点,变量a保持不变,它打印4。后来我知道我需要使用指针或引用;为什么呢

#include <iostream>

void setToTen(int x) { x = 10; }

int main(){  
    int a = 4;
    setToTen(a);
    std::cout << a << std::endl;
}
#包括
void setToTen(int x){x=10;}
int main(){
INTA=4;
setToTen(a);

STD::C++函数中的函数CUT< P>是通过值传递的。这意味着当你写

setToTen(a);
setToTen
中的参数
int x
被赋予变量
a
中存储的值的副本。换句话说,您实际上并没有将变量
a
传递到
setToTen
函数中。相反,您将该值的副本传递给
setToTen
,因此该函数中所做的更改离子会影响副本而不是原件

另一方面,如果更改
setToTen
,使其通过引用获取其参数,如下所示:

void setToTen(int& x) {
    x = 10;
}
故事不同。这里,调用
setToTen(a)
本质上是将变量
a
放入函数
setToTen
,而不是值的副本。这意味着对
setToTen
中的参数
x
所做的更改将更改变量
a
您的代码通过签名
void setToTen请求
x
的副本(int x)

能够通过复制获取内容意味着对函数行为的推理要容易得多。这对您和编译器都是如此

例如,想象一下:

int increase_some( int x, int y, int z ) {
  for (int i = 0; i < y; ++i )
    x+=z;
  return x;
}
并生成该输出

这是一个玩具示例,但我们将一个复杂函数转化为一个简单的函数。真正的优化器总是使用复杂函数的片段来实现这一点

更进一步,通过使用不可变值,并且从不涉及全局状态,我们可以将代码视为“函数”,只取决于其参数。这意味着编译器可以重复调用函数,并将其减少为一次调用

这是非常有价值的,编译器会将不具有原始数据不变副本的代码转换为在尝试优化之前具有原始数据不变副本的代码——这称为静态单赋值形式

从理论上讲,一个复杂的程序,有很多函数引用,可以用同样的方法进行优化,不会丢失任何东西。但在实践中,这会变得很困难,而且很容易意外地把它搞砸

这是另一面,使人们更容易推理


您所要接受的就是按值获取参数的思想。

函数参数是函数局部变量,在退出函数后不活动

您可以想象函数定义及其调用

int a = 4;
setToTen(a);

//...

void setToTen(int x) { x = 10; }
下面的方法

int a = 4;
setToTen(a);

//...

void setToTen( /* int x */ ) { int x = a; x = 10; }
int a = 4;
setToTen(a);

//...

void setToTen( /* int x */ ) { int &x = a; x = 10; }
从函数中可以看出,声明了一个局部变量
x
,该变量由参数
a
初始化。局部变量
x
的任何更改都不会影响原始参数
a

如果您想更改原始变量本身,您应该通过引用传递它,即函数将处理对该变量的引用

void setToTen(int &x) { x = 10; }
void setToTen(int *x) { *x = 10; }
在这种情况下,您可以想象函数定义及其调用如下

int a = 4;
setToTen(a);

//...

void setToTen( /* int x */ ) { int x = a; x = 10; }
int a = 4;
setToTen(a);

//...

void setToTen( /* int x */ ) { int &x = a; x = 10; }
正如您所看到的,引用
x
像往常一样是本地的。但是它引用了原始参数
a
。在这种情况下,参数将通过本地引用进行更改

另一种方法是将参数声明为指针

void setToTen(int &x) { x = 10; }
void setToTen(int *x) { *x = 10; }
在这种情况下,您必须通过其地址间接传递原始参数

int a = 4;
setToTen( &a );

根据语言规则中的定义,变量按值传递或复制到函数,除非它们是引用。您需要将
x
声明为按引用。即
int&
而不是
int
。这不是问题所在,但您真的需要
std::endl
所做的额外工作吗?
'\n
结束一行。可能重复的问题不应被否决,因为它们是基本问题或初学者问题。此问题说明预期行为、观察到的行为并提供答案。如果缺乏研究,这是一个很好的问题。特别是针对新用户。@marouanejaakik:如果这个答案令您满意,请接受它。