在学习 C++ 时,常常会遇到访问对象成员的两种符号:. 和 ->。这两个符号看似简单,但它们的正确使用却需要理解指针和对象的本质差异。对于 C/C++ 小白来说,这篇文章将详细解释它们的区别,帮助你在编程时少踩坑。
一、. 与 -> 的基本概念
在 C++ 中,. 和 -> 是用来访问类(或结构体)成员的操作符。它们的使用场景有所不同:
这两个操作符的作用是类似的,但它们适用的对象类型不同。
二、. 的用法
点号操作符 . 是最简单的成员访问操作符,适用于普通对象。通过对象名和点号,我们可以直接访问该对象的成员函数或成员变量。
示例代码
1 2 3 4 5 6 7 8 9 10 11 12 13 |
#include <iostream> using namespace std; class Stack { public: void enstack(int value) { cout << "Value enstacked: " << value << endl; } }; int main() { Stack s; // 创建一个普通对象 s.enstack(1); // 通过 . 访问成员函数 return 0; } |
输出结果
Value enstacked: 1
在这里,s 是一个普通对象,s.enstack(1) 通过点号直接调用对象 s 的 enstack 函数。
总结 如果你创建的变量是一个普通对象(栈分配或静态分配),就用 . 访问其成员。点号操作符只能用于非指针对象。
三、-> 的用法
箭头操作符 -> 用于指针对象。它的作用是隐式解引用指针,访问指针所指对象的成员。
示例代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#include <iostream> using namespace std; class Stack { public: void enstack(int value) { cout << "Value enstacked: " << value << endl; } }; int main() { Stack *s = new Stack(); // 创建一个指针对象 s->enstack(1); // 通过 -> 访问成员函数 delete s; // 释放动态分配的内存 return 0; } |
输出结果
Value enstacked: 1
在这里,s 是一个指向 Stack 对象的指针,s->enstack(1) 隐式解引用该指针并访问其成员函数 enstack。
总结
四、. 和 -> 的等价关系
-> 实际上是 (*pointer).member 的简写。这一点可以通过以下代码理解:
示例代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
#include <iostream> using namespace std; class Stack { public: void enstack(int value) { cout << "Value enstacked: " << value << endl; } }; int main() { Stack *s = new Stack(); // 使用 -> 操作符 s->enstack(1); // 等价于使用解引用和点号 (*s).enstack(1); delete s; // 释放内存 return 0; } |
输出结果
Value enstacked: 1
Value enstacked: 1
通过这段代码可以看出,s->enstack(1) 和 (*s).enstack(1) 是完全等价的。
为什么有 ->?
如果没有 ->,我们每次都需要先解引用指针再用点号访问成员,写起来会显得冗长。例如:
1 |
(*pointer).memberFunction(); |
而 -> 直接简化了这一过程,代码更简洁:
1 |
pointer->memberFunction(); |
五、如何判断用哪个操作符?
检查变量类型:
错误提示:
如果你试图对指针对象使用 .,或者对普通对象使用 ->,编译器会报错:
以下是常见错误示例:
1 2 3 4 5 |
Stack *s = new Stack(); // 错误:指针不能直接用点号访问 s.enstack(1); // 正确:使用箭头操作符 s->enstack(1); |
六、实战对比示例
以下是一个综合示例,展示如何在不同情况下使用 . 和 ->:
示例代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
#include <iostream> using namespace std; class Stack { public: void enstack(int value) { cout << "Value enstacked: " << value << endl; } }; int main() { // 普通对象 Stack obj; obj.enstack(10); // 指针对象 Stack *ptr = new Stack(); ptr->enstack(20); delete ptr; // 释放内存 return 0; } |
输出结果
Value enstacked: 10
Value enstacked: 20
七、注意事项
指针初始化:
内存管理:
智能指针:
八、总结
了解这些基本概念后,可以避免在访问对象成员时犯错。