首页 > 代码库 > C++中Reference与指针(Pointer)的使用对比

C++中Reference与指针(Pointer)的使用对比

我们已经知道在C++中,对象变量直接存储的是对象的值。这是与Java不同的,在Java中对象变量存储的是一个地址,该地址指向对象值实际存储的地方。有时在C++中也需要实现这样的布置,这就用到了指针pointer。在 C++中,一个指向对象的变量叫做指针。如果T是一种数据类型,则T* 是指向这种数据类型的指针。 这里重点介绍C++与Java的不同,要详细了解C++中指针的使用

就像 Java中一样,一个指针变量可以被初始化为空值 NULL,另外一个指针变量的值,或者一个调用new生成的新对象:

Employee* p = NULL;

Employee* q = new Employee("Hacker, Harry", 35000);

Employee* r = q;

实际上在C++中还有第四种可能,那就是指针可以被初始化为另外一个对象的地址,这需要使用地址操作符 &

Employee boss("Morris, Melinda", 83000);

Employee* s = &boss;

这实际上并不是什么好主意。保险的做法还是应该直接让指针指向使用 new生成的新对象。

到目前为止,C++ 指针看起来非常像 Java 的对象变量。然而,这里有一个很重要的语法的不同。我们必须使用星号操作符 * 来访问指针指向的对象。如果p 是一个指向Employee对象的指针,则 *p 才代表了这个对象:

Employee* p = . . .;

Employee boss = *p;

当我们需要执行对象的函数或访问对象的一个数据域时,也需要使用 *p

(*p).setSalary(91000);

*p外面的括号是必需的,因为 . 操作符比 * 操作符有更高的优先级。C的设计者觉得这种写法很难看,所以他们提供了另外一种替代的写法,使用 -> 操作符来实现*. 操作符的组合功能。表达式

p->setSalary(91000);

可以调用对象*p的函数 setSalary 。你可以简单的记住 . 操作符是在对象上使用的,-> 操作符是在指针上使用的。

如果你不初始化一个指针,或者如果一个指针为空值 NULL 或指向的对象不再存在,则在它上面使用 *-> 操作符就会出错。 不幸的是 C++ runtime 系统并不检查这个出错。如果你范了这个错误,你的程序可能会行为古怪或死机。

而在Java中,这些错误是不会发生的。所有的reference都必须初始化,所有的对象只要仍有reference指向它就不会被从内存中清除,因此你也不会有一个指向已被删除的对象的reference。Java的runtime 系统会检查reference是否为空,并在遇到空指针时抛出一个null pointer的例外(exception)。

C++ 和 Java还有一个显著的不同,就是 Java 有垃圾回收功能,能够自动回收被废弃的对象。而在C++中,需要程序员自己管理内存分配回收。

C++中当对象变量超出范围时可以自动被回收。但是使用new生成的对象必须用delete操作符手动删除,例如:

Employee* p = new Employee("Hacker, Harry", 38000);

. . .

delete p; /* 不在需要这个对象 */

如果你忘记删除一个对象,那么你的程序有可能最终用光所有内存。这就是我们常说的内存泄漏 (memory leak)。更重要的是,如果你如果删除了一个对象,然后又继续使用它,你可能覆盖不属于你的数据。如果你刚巧覆盖了用于处理内存回收的数据域,那么内存分配机制就可能运转失常而造成更严重的错误,而且很难诊断和修复。因此,在C++中最好尽量少用指针。

C++中Reference与指针(Pointer)的使用对比