1. 点号与箭头操作符的本质区别
在C++中,点号(.)和箭头(->)操作符都是用于访问类成员的运算符,但它们的适用场景有着本质区别。理解这个区别需要从C++的对象模型说起。
1.1 内存访问的基本原理
当我们声明一个对象时,例如:
cpp复制MyClass obj;
这个对象会被分配在栈上(如果是局部变量)或全局/静态存储区。此时,我们可以直接使用点号访问其成员:
cpp复制obj.memberFunction();
而当使用指针时:
cpp复制MyClass* ptr = &obj;
ptr存储的是obj的内存地址,要访问成员就需要先解引用。这就是箭头操作符的由来:
cpp复制ptr->memberFunction(); // 等价于 (*ptr).memberFunction()
1.2 编译器视角的差异
从编译器实现角度看:
- 点号操作:直接计算成员在对象内的偏移量
- 箭头操作:先解引用指针,再计算成员偏移量
这种差异在汇编层面会表现为不同的指令序列。理解这一点有助于我们在性能敏感场景做出正确选择。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 具体使用场景分析
2.1 必须使用点号的场景
- 栈对象访问:
cpp复制std::vector<int> vec;
vec.push_back(10); // 正确用法
- 引用类型访问:
cpp复制auto& ref = vec;
ref.size(); // 引用虽然底层是指针,但语法上使用点号
- 右值引用访问:
cpp复制auto&& rref = std::move(vec);
rref.clear(); // 右值引用也使用点号
2.2 必须使用箭头的场景
- 原始指针访问:
cpp复制std::vector<int>* pvec = &vec;
pvec->push_back(20); // 指针必须用箭头
- 智能指针访问:
cpp复制auto sptr = std::make_shared<std::vector<int>>();
sptr->push_back(30); // 智能指针重载了->操作
