我是一名学习C ++的初学者,并且通过引用传达了一个关于传递参数的章节。交换函数定义如下:
void swap(double& d1, double& d2)
{
double temp = d1;
d1 = d2;
d2 = temp;
}
测试是这样的,并且它有效,交换了值:
int main()
{
double x = 1;
double y = 2;
cout << "X==" << x << "y==" << y << '\n';
swap(x,y);
cout << "x==" << x << "y==" << y << '\n';
}
但是我不能为我的生活弄清楚为什么删除引用会使这段代码无效:
void swap(double d1, double d2)
{
double temp = d1;
d1 = d2;
d2 = temp;
}
我已经这样做了,因为我想更好地理解参考文献,因为正确理解它们使我望而却步。我希望得到一个正确方向的答案或指针。
答案 0 :(得分:3)
在程序编程语言中有一些常见的概念,比如C ++的“按值传递”和“按引用传递”。
当一个变量按值传递给一个过程(或函数)时,一个副本由变量组成,过程(或函数)中的任何修改都不会反映在变量传递的值强>
相反,当变量通过引用传递时,修改会反映在通过引用传递的变量中。
C ++中的术语 reference 指的是这个想法所以在参考案例中swap()
的行为交换作为参数传递的原始变量,在第二种情况下它们不会。
如果您看到一个名为void foo(int x)
的函数foo(b);
,您应将其视为“复制b
并在该副本上执行foo
”。
如果是void foo(int &x)
则会直接在foo
上执行b
。
答案 1 :(得分:2)
让我们用一个类比......你有一张纸,上面写着两个数字。现在您希望朋友交换这两个值。这样:
void swap(double d1, double d2) {
double temp = d1;
d1 = d2;
d2 = temp;
}
就像你拿第二张纸,在上面写上数字,把它交给你的朋友(按值传递),他交换价值但不向你返回任何内容(void
返回类型) 。这种改变会改变你纸上的数字吗?没有。
让我们改变策略:你现在告诉他在哪里可以找到你的纸张,而不是给你的朋友一份你的数据副本,这样他就可以直接在那里完成工作(通过引用传递):
void swap(double& d1, double& d2) {
double temp = d1;
d1 = d2;
d2 = temp;
}
他仍然不需要向你返回任何东西,因为一旦完成,你只需要查看你的纸张以查看交换的值。
PS:类比总是有它们的限制,所以要带上一粒盐。答案 2 :(得分:1)
传递引用就像传递&#34;事物本身&#34;而不仅仅是它的价值。
如果你把朋友的戒指交给朋友,让它们以任何方式用它捣乱,然后把它取回来。 通过价值传递就像给朋友递上一个看起来就像你的珍贵戒指的戒指一样,他们可以保留它,并保持你的,不受他们肮脏,窃听的手指的影响。
比swap
更简单的例子:
void fv(int x)
{
x = 0;
}
如果您将变量传递给此变量,则该变量的值将复制到完全独立的变量x
中。
x
将具有与您的变量相同的值,但它不会是相同的事物。
当您为x
分配值时,您将分配给此变量,而不是将其值复制到其中的变量。
void fr(int& x)
{
x = 0;
}
如果您将变量传递给此变量 - fr(v)
- x
您的变量;名字&#34; x&#34;和&#34; v&#34;引用相同的事物
在函数内部为x
赋值与在调用代码中为v
赋值完全相同。
答案 3 :(得分:0)
在第一个示例中,您将传递双精度作为参考。改变函数内部的值,改变双x和...在你的主要。
在第二个示例中,您将传递双精度值作为值。这意味着,他们的价值被复制即。创建两个新的双精度并传递给函数。通过更改这些值,您可以修改复制的双打 - 而不是x&amp;你的主人。
答案 4 :(得分:0)
因为默认情况下,当您将变量作为函数参数传递时,它会按值传递。这意味着(比如在下面的代码中)传递给函数时,它实际上创建了它的副本,并且您不再使用原始变量并且使用其副本进行操作 - 它具有相同的值但在内存中具有不同的位置。
int myVar = 10;
void f(int var) {
var = 20;
}
// here the value of myVar is 10
f(myVar);
// here the value of myVar is still 10
通过引用传递变量完全是因为您展示的示例。您想要创建一个函数,该函数实际上可以修改函数范围之外的传递变量的值。
int myVar = 10;
void f(int& var) {
var = 20;
}
// here the value of myVar is 10
f(myVar);
// here the value of myVar is still 20
您可以将其视为定义
这在使用字符串时经常使用。例如:假设您在变量std::string packet
中获取数据包数据,并且您想要创建一个分析它的函数。你可以做这样的事情
std::string packet;
someResultType func(std::string packet) {
....
}
auto result = function(packet);
但是在这个例子中,创建一个新的变量包副本是完全没用的,因为在使用它时,你可能不会修改它,所以你对编译器说 - 我保证我不会修改它的值因此,您可以通过引用传递值:
std::string packet;
someResultType func(const std::string& packet) {
// you're working with the global packet but you cant modify it
}
auto result = function(packet);