【发布时间】:2010-09-15 00:39:36
【问题描述】:
什么是“值语义”,什么是“隐式指针语义”?
【问题讨论】:
标签: java c++ terminology semantics
什么是“值语义”,什么是“隐式指针语义”?
【问题讨论】:
标签: java c++ terminology semantics
Java 对 Object 类型使用隐式指针语义,对基元使用值语义。
值语义意味着您直接处理值并传递副本。 这里的重点是,当您拥有价值时,您可以相信它不会在您背后改变。
使用指针语义,您没有值,只有“地址”。 其他人可以改变那里的东西,你不知道。
C++ 中的指针语义:
void foo(Bar * b) ...
... b->bar() ...
你需要一个 * 来请求指针语义和 -> 调用指针上的方法。
Java 中的隐式指针语义:
void foo(Bar b) ...
... b.bar() ...
由于您无法选择使用值语义,因此不需要 * 也不需要区分 -> 和 .,因此是隐含的。
【讨论】:
基本上,值语义意味着将一个值分配给另一个值会创建一个副本:
int x = 1;
int y = x;
x = 2; // y remains the same!
一种特殊情况是一个函数调用,它传递了一个参数:
void f(int x) {
x = 5;
}
int a = 1;
f(a);
// a is still 1
这实际上对于 Java 和 C++ 是一样的。然而,Java 只知道一些基本类型,其中包括int、double、boolean 和char,以及以这种方式运行的枚举。所有其他类型都使用引用语义,这意味着将一个值分配给另一个实际上会重定向指针而不是复制底层值:
class Foo {
int x;
public Foo(int x) { this.x = x; }
}
Foo a = new Foo(42);
Foo b = a; // b and a share the same instance!
a.x = 32;
//b.x is now also changed.
但是有一些注意事项。例如,许多引用类型(String、Integer ...)实际上是不可变的。它们的值不能更改,对它们的任何赋值都会覆盖旧值。
此外,参数仍然按值传递。这意味着传递给函数的对象的值可以更改,但其引用不能:
void f(Foo foo) {
foo.x = 42;
}
void g(Foo foo) {
foo = new Foo(42);
}
Foo a = new Foo(23);
f(a);
// a.x is now 42!
Foo b = new Foo(1);
g(b);
// b remains unchanged!
【讨论】:
Java 是按值传递的。 C++ 可以同时使用值和引用语义。
【讨论】:
Java 在变量访问上使用implicit pointer semantics(您不能直接编辑引用,它会自动(隐式)解析为访问时的对象)并且还在上使用Pass-by-Value semantics方法参数传递。
阅读Pass-by-value semantics in Java applications:
在 Java 应用程序中,当一个对象 引用是方法的参数, 您正在传递一份 参考(按值传递),而不是 引用自己。请注意, 调用方法的对象引用和 副本指向同一个 目的。这是一个重要的 区别。一个 Java 应用程序 通过时没有什么不同 不同类型的参数,如 C++ 做。 Java 应用程序通过所有 参数值,从而使 所有参数的副本,无论 输入。
Short:Java 中的所有参数都是按值传递的。但这并不意味着对象被复制(就像 PHP4 中的默认值一样),而是对该对象的引用被复制。
你会在Pass-by-value semantics in Java applications看到所有的解释和深入的例子
【讨论】: