将 Java 的按值传递与C++的按值传递或引用进行比较
Comparing Java's pass-by-value with C++'s pass-by-value or -reference
Java使用传递值,同时使用对象和基元类型。因为Java传递引用的值,所以我们可以更改target的值,但不能更改地址。
这与C++相比如何?
区别在于是否可以影响调用函数中的变量。
让我们暂时把物体放在一边。在纯按值传递的Java中,不能更改传递到被调用函数中的变量的调用函数的值。示例:
void foo() {
int a = 42;
bar(a);
System.out.println("foo says: " + a);
}
void bar(int a) {
a = 67;
System.out.println("bar says: " + a);
}
如果你打电话给foo
,你会看到:
酒吧说:67foo说:42
bar
无法更改foo
的a
。
在C++中,如果您传递值,则情况也是如此。但是,如果您通过引用,则将参考传递给调用代码的变量。这意味着被调用的代码可以改变它:
void foo() {
int a = 42;
bar(a);
cout << "foo says: " << a;
}
void bar(int& a) {
a = 67;
cout << "bar says: " << a;
}
注意,bar
被定义为接收引用(int& a
)。如果你打电话给bar
,你会看到:
酒吧说:67foo说:67
bar
能够在foo
内更改a
的值。
好吧,让我们来处理对象引用:首先,请注意,"引用"一词用于两个完全不同的东西:对调用函数中的变量的reference(这是通过引用的东西),以及对对象的reference。当您将对象引用传递到Java中的方法中时,该引用将通过值传递,就像其他一切一样。
void foo() {
List list = new ArrayList();
List ref2 = list; // (Let's remember that object reference for later...)
bar(list);
System.out.println("foo says: " + list.size());
System.out.println("foo says: Same list? " + (ref2 == list));
}
void bar(List list) {
// `bar` can modify the state of the object the reference points to
list.add(new Object());
System.out.println("bar says (after add): " + list.size());
// ...but cannot change `foo`'s copy of `list`
list = new ArrayList();
System.out.println("bar says (after new): " + list.size());
}
所以你看到了:
酒吧说(添加后):1酒吧说(在新的之后):0傅说:1傅说:同样的名单?true
bar
可以更改其引用(按值)传入的对象的状态,但不能更改foo
对该对象的引用。foo
没有看到创建的新列表bar
。
在Java中,您可以通过值传递基元和引用。没有其他选择。
在C++中,可以通过值或引用传递基元和指针。如果通过引用传递,则可以看到在将值或指针传递给方法后对其所做的更改,并且可以更改原始值。
区别在于是否可以影响调用函数中的变量。
让我们暂时把物体放在一边。在纯按值传递的Java中,不能更改传递到被调用函数中的变量的调用函数值。示例:
void foo() {
int a = 42;
bar(a);
System.out.println("foo says: " + a);
}
void bar(int a) {
a = 67;
System.out.println("bar says: " + a);
}
如果你调用foo,你会看到:
酒吧说:67傅说:42酒吧无法更改foo的a.
在C++中,如果您传递值,则情况也是如此。但是,如果通过引用传递,则传递对调用代码的变量的引用。这意味着被调用的代码可以改变它:
在C++中,与Java等价的东西就是这个
void Swap(Type* A, Type* B)
{
// here we have pointers to type A (in Java they are called references and don't use * syntax)
A->DoThis() // can call with -> a method on object
//if you try to swap A with B not possible because we don't have A*/B* reference
// see bellow how to do this
}
在C++中处理上述限制的方法是
void Swap(Type& A, Type& B)
{
Type& temp = A;
A = B;
B = temp;
}
- 何时应通过引用传递矢量参数而不是按值传递矢量参数?
- C++类 - 初始化列表 - 递归 - 按值传递
- 将函数参数完美转发到函数指针:按值传递呢?
- 棘手的按值传递和按引用递归问题传递
- 不同于按值传递和常量引用传递的程序集
- 按值传递变量与按引用传递变量具有相同的结果
- 为什么按值传递QStringView比引用常量更快?
- 获取 std::函数以推断按引用传递/按值传递
- 在函数中按值传递 unordered_map/unordered_set 是否有效? C++
- C++/11 auto 关键字是在更有效时推导参数进行按引用传递,还是始终按值传递?
- 使用 enable_if 在按值传递与按引用传递之间更改函数声明
- 防止在按值传递对象(继承)时进行切片
- 按值传递类和结构
- C++按引用传递还是按值传递?
- 为什么在按值返回时创建临时对象,而不是在按值传递给函数参数时创建临时对象
- 可移动但不可复制的对象:按值传递还是按引用传递?
- const-ref传递的模板化参数是否经过优化,以便在足够小时按值传递
- 通过查看程序集来比较按值传递与按引用传递性能
- 将 Java 的按值传递与C++的按值传递或引用进行比较
- 在比较函数中按值传递与非const引用传递与const引用传递