我想要澄清按值传递和按引用传递之间的区别。我画了一张图,如下所示:
因此,通过按值传递,将创建一个相同对象的副本,并分配新的引用,使局部变量指向新的副本。如果函数修改该值,则无论是按值传递还是按引用传递,都会在调用函数的作用域内看到这些修改。
![Enter image description here](https://istack.dev59.com/fNEsL.webp)
我认为许多混淆是由于没有明确表达“按引用传递”的含义所致。当有些人说“按引用传递”时,他们通常指的不是参数本身,而是被引用的对象。其他一些人则认为“按引用传递”意味着在被调用者中不能更改该对象。例如:
struct Object {
int i;
};
void sample(Object* o) { // 1
o->i++;
}
void sample(Object const& o) { // 2
// nothing useful here :)
}
void sample(Object & o) { // 3
o.i++;
}
void sample1(Object o) { // 4
o.i++;
}
int main() {
Object obj = { 10 };
Object const obj_c = { 10 };
sample(&obj); // calls 1
sample(obj) // calls 3
sample(obj_c); // calls 2
sample1(obj); // calls 4
}
sample(&obj);
// yields a `Object*`. Passes a *pointer* to the object by value.
// The caller can change the pointer (the parameter), but that
// won't change the temporary pointer created on the call side (the argument).
sample(obj)
// passes the object by *reference*. It denotes the object itself. The callee
// has got a reference parameter.
sample(obj_c);
// also passes *by reference*. the reference parameter references the
// same object like the argument expression.
sample1(obj);
// pass by value. The parameter object denotes a different object than the
// one passed in.
这意味着以下内容是按值传递的:如果被调用的函数的相应参数具有引用类型并且引用参数直接绑定到参数表达式(8.5.3/4),则仅当参数(1.3.1)按引用传递。在所有其他情况下,我们必须使用按值传递。
void f1(Object const& o);
f1(Object()); // 1
void f2(int const& i);
f2(42); // 2
void f3(Object o);
f3(Object()); // 3
Object o1; f3(o1); // 4
void f4(Object *o);
Object o1; f4(&o1); // 5
1
是按值传递,因为它没有直接绑定。实现可能会复制临时变量,然后将该临时变量绑定到引用上。2
是按值传递,因为实现会初始化一个字面量的临时变量,然后将其绑定到引用上。3
是按值传递,因为参数没有引用类型。4
由于同样的原因也是按值传递。5
是按值传递,因为参数没有引用类型。根据8.5.3/4和其他规则,以下情况是按引用传递:
void f1(Object *& op);
Object a; Object *op1 = &a; f1(op1); // 1
void f2(Object const& op);
Object b; f2(b); // 2
struct A { };
struct B { operator A&() { static A a; return a; } };
void f3(A &);
B b; f3(b); // passes the static a by reference
当按值传递时:
void func(Object o);
然后调用
func(a);
Object
,并且在func
的实现中,它将被o
引用。这可能仍然是浅拷贝(a
和o
的内部可能指向相同的数据),因此a
可能会更改。但是,如果o
是a
的深层副本,则a
将不会更改。
通过引用传递:
void func2(Object& o);
func2(a);
您将仅提供一种引用a
的新方式。 "a
"和"o
"是同一对象的两个名称。在func2
中更改o
将使这些更改对调用者可见,调用者通过名称"a
"知道该对象。
我对“如果函数修改了该值,则无论是按值传递还是按引用传递,这些修改都会出现在调用函数的范围内”这句话的理解是,它们是错误的。
当按值传递时,在被调用的函数中进行的修改不会在调用函数的范围内。
要么您输入引用的文字有误,要么它们已经从上下文中提取出来,使得看起来是错误的,正确的。
请确保您已正确引用您的来源,如果没有错误,请提供更多包含该语句的源材料文本。