【发布时间】:2011-06-14 17:54:44
【问题描述】:
在:http://www.horstmann.com/ccj2/ccjapp3.html,在 A3.4 下。对象,提及以下内容:
在 C++ 中,对象变量保存值,而不是对象引用
你能澄清这一点吗?而且,是否只有 C++ 中的 pointer 持有对象引用?
我们可以在这里说object reference 是object address 吗?
谢谢。
【问题讨论】:
在:http://www.horstmann.com/ccj2/ccjapp3.html,在 A3.4 下。对象,提及以下内容:
在 C++ 中,对象变量保存值,而不是对象引用
你能澄清这一点吗?而且,是否只有 C++ 中的 pointer 持有对象引用?
我们可以在这里说object reference 是object address 吗?
谢谢。
【问题讨论】:
你能澄清一下吗?
最好通过比较来理解,例如Java 或 C#:
MyClass a = new MyClass; // creates an instance.
MyClass b = a; // we still have one instance of MyClass in memory
对比在 C++ 中:
MyClass a; // a *is* an instance of MyClass.
MyClass b = a; // we make a copy of a, now there are *two* instances of MyClass.
而且,只有 C++ 中的指针持有对象引用吗?
不,参考也是。
这里可以说对象引用就是对象地址吗?
不,如果您的意思是 A& 引用,那么它是一个实现细节。您也可以使用类似于 C# 的引用语义来实现对象。 pugixml 库中的xml_node 就是一个例子:
xml_node root = ...;
xml_node root2 = root; // doesn't copy the document
// root2 refers to the same object as root.
【讨论】:
C++ 支持值/指针/引用的概念。一个值就像一个 Java int 如果你将它传递给一个修改参数的函数,原始值是不变的,这就是所谓的值语义。
在 Java 中,大多数对象都有引用语义,这意味着变量不存储对象,它存储对对象的引用,因此如果通过一个引用修改对象,所有其他引用都会看到更改。这在 C++ 中也支持引用和指针。指针是对象的内存地址,引用的行为在语义上相似(通常在幕后用指针实现)。说引用是对象的地址是不正确的,对象的地址是指向对象的指针。
【讨论】:
这可能有点太详细了,但是,准确的说,指针是一个对象变量,它存储着另一个对象的地址,并且有一个自身的实体:你可以请求指针的地址,你可以修改一个指针……
引用(C++ 意义上的,而不是 Java)不是对象变量(在当前的标准中,我相信 c++0x 对此有一些改写),而是对象的别名。围绕这一点有一些技术细节,例如您可以创建对象数组,但不能创建引用数组(引用不是对象)。
现在,如果您有 Java 背景,您真正需要记住的是(虽然不完全相同)Java 变量和 C++ 指针是相似的东西:它们持有访问某处对象的密钥,但是C++ 引用的概念在 Java 中不可用。这就是你不能在Java中实现swap操作的原因,除了一些特定的类型:
template <typename T>
void swap( T & lhs, T & rhs )
{
T tmp = lhs;
lhs = rhs;
rhs = tmp;
}
int main() {
int a = 1, b = 5;
swap( a, b ); // a == 5, b == 1 after this call in this context
}
如果您牢记这一点并且理解在 Java 中引用是按值传递的(引用的副本被传递给函数),那么您在理解 C++ 函数调用语义方面已经迈出了很好的一步。
【讨论】:
对象引用是对象的永久、固定和隐式地址。而指针是可变的、显式的地址变量。换句话说,引用使用对象的地址来访问对象,但是 1) 它不会使程序员可以使用该地址,并且 2) 引用永久绑定到特定对象。指针可以指向特定类型的任何对象,或者根本不指向任何对象。初始化不是强制性的。此外,由于指针是变量,因此可以随意重新分配。
【讨论】:
是的,在 C++ 指针中保存对象引用,还有 & 运算符也可以进行隐式引用。 Java 和 c++ 有不同的行为。 在java中:
myobject a;
a = new myobject();
在 C++ 中:
myobject a;
或 我的对象 *a; a = new myobject();
【讨论】:
在 C++ 中,默认是按值传递和存储对象。所以如果你有
class A {
int x[5000];
}
这将创建一个存储 5000 个整数的类型。如果你有一个像这样使用 A 的类:
class B {
A content;
};
那么每个 B 都有一个包含 5000 个整数的数组。这与 Java 这样的语言形成鲜明对比,Java 的内容类似于指向 A 的指针。
在 C++ 中,您可以选择将内容作为指向 A 的指针:
class C {
A* content;
};
或对 A 的引用
class D {
A& content;
};
但您必须明确地这样做。另外,C++ 中的引用不能为空,所以如果 content 的值可能是未定义的,则必须使用指针。
【讨论】:
事实上,C++ 中有三种不同的变量。值、引用和指针。第一个,价值,意味着如果你定义
int a;
或
SomeOtherType a;
这意味着您创建了该类型的新对象,并且保留了内存来存储它。然后你可以例如通过编写将其内容复制到另一个变量
another_variable = a;
如果你改用指针,像这样:
SomeType *a = &some_existing_variable;
如果你说“b = a;”其中 a 和 b 都是指针,您不会复制任何数据,而只需更改这些指针指向的对象。参考文献的工作方式大致相同。指针和引用之间最重要的区别是引用不能为 NULL,必须初始化引用,不能更改引用的值,并且它们使用的语法不同。
【讨论】:
解释对象变量和指针变量之间差异的最直观的方法之一与分配内存的位置有关:对象变量引用堆栈对象,而指针(和引用)可能(通常)引用堆对象。两者构造不同,寿命不同,各有优缺点。
查看我文章的“堆栈和堆”部分: http://akos.ma/188y
【讨论】: