#include<iostream>
using namespace std;
int& add() {
static int a;
a++;
cout<<"\na="<<a;
return a;
}
int main {
int x,y,m;
int &z = add(); //it behaves as a reference to "a" which is a static variable
x=add();//why does it work correctly
y=add();//why does it work correctly
z++;
m=add();//why does it work correctly
cout<<"\nx="<<x<<"\ny="<<y<<"\nz="<<z<<"\nm="<<m;
return 0;
}
output:
a=1
a=2
a=3
a=5
x=2
y=3
z=5
m=5
内部恰好发生了什么 x,y,m&amp; ž
答案 0 :(得分:3)
int main{
int x,y,m; // declare three ints: x,y,m, all unassigned
int &z = add(); // a is incremented to 1, z is a reference to a
x=add(); // add() returns a reference to a, x copies the value of a
y=add(); // same as above
z++; // increments a, since z is a reference to a
m=add(); // same as x and y, copies the value of a
cout<<"\nx="<<x<<"\ny="<<y<<"\nz="<<z<<"\nm="<<m;
return 0;
}
所以你连续三次调用add()
,将a
增加到1,2,3(并且每次打印该值。
z
是对真实a
的引用。
x
,y
和m
是作业分配时a
的值的副本。所以x是2,y是3,我们通过z++
跳过4,然后m是5。
答案 1 :(得分:3)
int &z = add();
z
是对静态变量a
的引用。从现在开始,a
和z
是同义词。它们都指向相同的内存位置。
int x;
x = add();
x
是一个独立的内存位置。由于分配,x
将在调用时保留add()
个返回值。这就是y
和m
的工作原理。
答案 2 :(得分:2)
x
,y
和m
只是变量,因此它们会在调用a
时获得add
中的任何值,这就是它。如果要更改任何变量的值,则不会影响a
的值。由于z
是引用,因此它是静态a
变量的“指针”(在某种意义上),因此更改z
实际上会更改a
。
答案 3 :(得分:2)
引用是某个对象的另一个名称,别名。它就像是对象一样。
当add()
返回对a
的引用时,其行为就像返回的值 a
一样。
所以代码
x = add();
表现得像以前一样
a++;
x = a;
因此它捕获了a
此时的值。
另一方面,代码
int& z = add();
表现得像
a++;
int& z = a;
z
成为a
的另一个名称。从现在开始使用a
或z
并不重要,这意味着相同。仍然只有一个值,但该值有两个名称。我们可以使用其中任何一个来阅读或更新它。
就像我们使用Bob来引用一个名叫Robert的人一样 - 这个名字也是同一个东西。
答案 4 :(得分:1)
我相信这是它的工作原理:
在上下文中使用的引用,其中需要引用类型的(值)被隐式取消引用。这包括(其中包括):
在上面的上下文中,创建了引用值的副本。
无论何处需要引用,它们都被视为引用(显然不会被解除引用)。这包括:
在这些上下文中,不会创建引用值的副本。新引用只是现有值的新别名。
上述两种情境的语法是相同的,因此需要付出一些努力来查看正在发生的事情。
答案 5 :(得分:1)
引用只是一个常量指针,在某种意义上说,你可以改变指向的对象,但你不能指向其他东西。
当您需要值并允许使用*
而不是.
来访问成员时,C ++所做的只是让您免于添加指向解引用语法(一元->
)指向结构化的类型。
请注意,C ++中有一个使用const X&
的常见反模式,就好像这是一种比X
更智能的函数参数。请永远不要忘记引用基本上是指针,因此指向对象在使用时可能会改变甚至消失(const
并不意味着对象不会改变,只是你不能改变它使用它参考强>)。
有关在使用引用而非值时应注意的原因的更详细说明,请参阅this answer。
每当你看到一个引用时,你应该至少考虑一下,如果对象在你使用它的时候足够活跃和/或变异。在您的情况下,引用的对象是一个静态函数,因此生命周期没有问题(函数静态对象在您第一次进入定义它们的范围时就会出现,直到程序结束为止。)
将代码翻译成实际发生的事情(指针摆弄)
#include<iostream>
using namespace std;
int* add() {
static int a;
a++;
cout << "\na=" << a;
return &a; // we're returning a pointer to our static variable
}
int main(int argc, const char *argv[]) {
int x,y,m;
int *z = add(); // points to "a" which is a static variable
x = *add(); // just get the current value of (incremented) a
y = *add(); // same here, of course now different from x
(*z)++; // incrementing a from outside the function (we've a pointer!)
m = *add(); // once again just reading current incremented value
cout << "\nx=" << x << "\ny=" << y<< "\nz=" << (*z) << "\nm=" << m;
return 0;
}
答案 6 :(得分:1)
好的,让我们剖析这个小程序
int& add()
{
static int a;
a++;
cout<<"\na="<<a;
return a;
}
static int a声明一个变量。此上下文中的静态意味着只存储a,并且只要调用add,就会使用该位置。所以a就像一个只能在add中访问的全局变量。
返回值是参考。大多数编译器内部使用指针来表示引用。你在这里看到的是返回对静态变量a的引用。一旦获得参考,任何人都可以更改。
a ++和cout很简单 - 这里没有进一步的评论。
int main{
int x,y,m; // declare three ints: x,y,m, all unassigned
int &z = add(); // a is incremented to 1, z is a reference to a
x=add(); // add() returns a reference to a, x copies the value of a
y=add(); // same as above
z++; // increments a, since z is a reference to a
m=add(); // same as x and y, copies the value of a
cout<<"\nx="<<x<<"\ny="<<y<<"\nz="<<z<<"\nm="<<m;
return 0;
}
int&amp; z = add();调用add - 这意味着a递增。 z现在是静态变量a的别名,因为它使用了引用。 X =添加();再次增加a但现在复制a的值,因为x不是int&amp;类型但是类型为int。哟 - 相同。 z ++:因为z是a的别名 - 增加a而不通过cout打印它。
m = add():增加a,复制像m和y一样的int。
一旦你理解为什么x,y,m是副本而z是别名,输出就很简单。
还有问题吗?
问候
托拜厄斯