我写了这个小程序来解释我的观点和我的变量a保持不变它打印4.我后来才知道我需要使用指针或引用;那是为什么?
#include <iostream>
void setToTen(int x) { x = 10; }
int main(){
int a = 4;
setToTen(a);
std::cout << a << std::endl;
}
答案 0 :(得分:4)
在C ++中,函数的参数是按值传递。这意味着当你写
Arguments:
setToTen(a);
中的参数int x
被赋予存储在变量setToTen
中的值的副本。换句话说,您实际上并未将变量a
移交给a
函数。相反,您将该值的副本提供给setToTen
,因此该功能所做的更改会影响副本而不是原始副本。
另一方面,如果您更改setToTen
以便它通过引用获取其参数,如下所示:
setToTen
故事不同。在这里,调用void setToTen(int& x) {
x = 10;
}
实际上将变量setToTen(a)
传递给函数a
,而不是值的副本。这意味着对setToTen
中参数x
所做的更改将更改变量setToTen
。
答案 1 :(得分:3)
您的代码通过签名<div *ngIf="user != null">
...menu items...
</div>
来请求x
的副本。
能够通过 copy 来处理事情意味着对函数行为的推理要容易得多。这对您和编译器都是如此。
例如,想象一下:
void setToTen(int x)
因为int increase_some( int x, int y, int z ) {
for (int i = 0; i < y; ++i )
x+=z;
return x;
}
x
和y
是副本,所以您可以推断出这一点。如果他们引用价值&#34;外面&#34; z
的{{1}}可能会改变increase_some
或x+=z
,而事情可能会变得疯狂。
但是因为我们知道它们是副本,我们可以说y
如果z
则返回increase_some
,否则返回x
。
这意味着优化器可以将其更改为:
y<=0
并生成该输出。
这是一个玩具示例,但我们采用了复杂的功能并将其转换为简单的功能。真正的优化器会一直使用复杂函数来完成此任务。
更进一步,通过使用不可变值来处理事物,并且从不接触全局状态,我们可以将您的代码视为&#34; functional&#34;,仅取决于其参数。这意味着编译器可以重复调用函数并将它们减少为一次调用。
这非常有价值,编译器会将没有原始数据的不可变副本的代码转换为在尝试优化之前执行的代码 - 这称为静态单一赋值形式。
从理论上讲,一个复杂的程序可以通过引用来优化各种功能,并且不会丢失任何东西。但是在实践中变得越来越难,并且非常容易意外搞砸了。
那是另一面;让人们更容易推理。
你必须接受的是按价值接受争论的想法。
答案 2 :(得分:0)
函数参数是退出函数后不存活的函数局部变量。
您可以想象功能定义及其调用
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; }
在函数中可以看到声明了一个局部变量x
,它由参数a
初始化。局部变量x
的任何更改都不会影响原始参数a
。
如果要更改原始变量本身,则应通过引用传递它,该函数将处理对变量的引用。例如
void setToTen(int &x) { x = 10; }
在这种情况下,您可以通过以下方式设想函数定义及其调用
int a = 4;
setToTen(a);
//...
void setToTen( /* int x */ ) { int &x = a; x = 10; }
如您所见,参考x
与往常一样是本地的。但它引用了原始参数a
。在这种情况下,参数将通过本地引用进行更改。
另一种方法是将参数声明为指针。例如
void setToTen(int *x) { *x = 10; }
在这种情况下,您必须通过其地址间接传递原始参数。
int a = 4;
setToTen( &a );