C++箭头操作符
内容不全,仅供参考。
Class: C++ClassByMyself
参考: Cherno
避免解引用指针的笨重,从而更简洁高效的编写。
箭头操作实际上相当于逆向引用指针。
下面这个例子就能向你展示,重载箭头运算符的用处:
class ScopePtr
{
private:
Entity* m_Obj;
public:
ScopePtr(Entity* entity)
:m_Obj(entity)
{
}
~ScopePtr()
{
delete m_Obj;
}
};
int main()
{
ScopePtr entity = new Entity();
entity.GetObject()->Print();
std::cin.get();
}
对比:
class ScopePtr
{
// ......
Entity* operator->()
{
return m_Obj;
}
};
int main()
{
ScopePtr entity = new Entity();
entity->Print();
std::cin.get();
}
操作实例:
输出内存值偏移量:(这段代码是一种在C++中获取类成员偏移量的技巧)
struct Vector3
{
float x, y, z;
};
int main()
{
// 获取Vector3::x的偏移量
int offset = (int)&((Vector3*)nullptr)->x;
std::cout << offset << std::endl; // 通常输出0
std::cin.get(); // 等待用户输入,防止控制台窗口立即关闭
}
1. 让我们逐步分解这个表达式:
(Vector3*)nullptr- 将空指针转换为**Vector3***类型>x- 访问这个"假"对象的成员x&(...->x)- 获取成员x的地址(int)- 将地址转换为整型
2. 为什么这样能得到偏移量?
关键点在于编译器处理成员访问的方式:
- 当访问**
ptr->x时,编译器实际生成的是ptr + offsetof(x)**的代码 - 即使**
ptr**是nullptr,计算偏移量也不需要实际访问内存 - 计算的是x相对于对象起始地址的偏移量
不安全!!!
更安全的替代方案
1. 使用标准offsetof宏
#include <cstddef> // 需要包含这个头文件
struct Vector3 {
float x, y, z;
};
int main() {
size_t offset = offsetof(Vector3, x); // 标准方法
std::cout << offset << std::endl;
}
2. C++17的改进
C++17引入了更类型安全的替代方案:
#include <cstddef>
struct Vector3 {
float x, y, z;
};
int main() {
constexpr size_t offset = std::offsetof(Vector3, x);
std::cout << offset << std::endl;
}
这种技术常用于:
- 序列化/反序列化:直接操作内存布局来读写对象
- 内存映射:将二进制数据映射到对象结构
- 低级网络编程:处理原始数据包
- 自定义容器:实现灵活的内存管理
- 当你把数据序列化为一串字节流,而你想要计算机计算某些东西的偏移量时,这是非常有用的,因为比如在做图形编程,游戏引擎的时候,总是要处理字节流。
工作原理图示
Vector3对象内存布局:
+---------+---------+---------+
| x | y | z | (每个float通常4字节)
+---------+---------+---------+
0 4 8 12 (字节偏移)
当ptr为nullptr(0)时:
&ptr->x = 0 + offsetof(x) = 0
&ptr->y = 0 + offsetof(y) = 4
&ptr->z = 0 + offsetof(z) = 8

1114

被折叠的 条评论
为什么被折叠?



