C++(普通指针和成员的区别、指针的使用场景和存储内容)

本文目的解决下面这个问题:我们一起加油吧!

什么情况下要使用指向类型中元素的指针,目的是什么,为什么在这里给的是一个空值,s存储的到底是什么?

以这个代码为例:

cpp 复制代码
struct Node {
	int value;
};

int main() {
	int* p = nullptr;
	int Node::* s = nullptr;
	s = &Node::value;
}

1.普通指针和成员指针的区别?

(1)普通指针:

cpp 复制代码
int* p = nullptr;

普通指针 p 指向int 变量 ,存的是内存地址

(2)成员指针:

cpp 复制代码
int Node::* s = nullptr;

成员指针 s 指向 Node 类里的一个 int 成员变量 存的是 ,成员在类里的偏移量

2.为什么都是等于nullptr,但是监测值不一样?

(1)int* p = nullptr;

  • 这是普通空指针,表示 "不指向任何内存地址"。
  • 在 32/64 位系统里,它就是一个全 0 的地址:
    • 32 位:0x00000000
    • 64 位:0x0000000000000000
  • 所以调试器里显示 0x00000000 {???},这是最直观的 "空地址"。

(2)int Node::* s = nullptr;

  • 这是成员指针空值,表示 "不指向任何类成员"。
  • 成员指针本质存的是偏移量,而不是内存地址。
  • 编译器为了区分 "空成员指针" 和 "偏移量 0",会用一个特殊值表示 nullptr:
    • 常见实现:用 -1(即全 1 的二进制,64 位就是 0xffffffffffffffff)
  • 所以调试器里显示 0xffffffffffffffff {???},这是编译器约定的 "空成员指针" 标记,不是地址,也不是有效偏移量。

3.什么情况下要使用成员指针?

当你需要把 "类里面的某个成员" 当作一个变量来传递、选择、复用的时候。

比如:

  • 你写一个通用函数,不知道要访问 Node 的哪一个成员
  • 想让调用者传进来 "你要访问哪个字段"
  • 实现类似 "反射""动态访问成员" 的效果
cpp 复制代码
struct Node {
    int a;
    int b;
};

// 这个函数可以打印 Node 的任意一个 int 成员
void show(Node& obj, int Node::* mem) {
    cout << obj.*mem << endl;
}

int main() {
    Node n{10, 20};
    show(n, &Node::a);  // 传成员 a
    show(n, &Node::b);  // 传成员 b
}

4.使用成员指针的目的是什么?

让 "类的成员" 可以像普通数据一样被传递、保存、复用。

普通指针保存的是:某个内存地址(一个具体变量)

成员指针保存的是:类内部 "哪个成员" 不绑定具体对象,可以对任意对象使用。

5. s 到底存储的是什么?

s 里存的不是内存地址! 它存的是:成员在结构体 / 类内部的偏移量(offset)

(1)偏移量是什么?

偏移量 = 从对象开头,到这个成员的距离(字节数)

你可以把一个 struct 对象想象成 一长排连续的小格子(字节):

  • 第 0 个字节
  • 第 1 个字节
  • 第 2 个字节......

一个成员在第几个字节开始,它的偏移量就是多少。

比如:

cpp 复制代码
struct Node {
	int value;
};

value 在对象开头,偏移是 0。所以 s 里实际存的数字是 0。

如果是:

cpp 复制代码
struct Node {
	char c;    // 0
	int value;  // 4
};

(2)监测值?

那么 s = &Node::value 时,s 里存的就是 4。

所以当代码执行到s=&Node::value这一行时,s由0xffffffff =>0x00000000

6.为什么这里给 nullptr?

cpp 复制代码
int Node::* s = nullptr;

原因和普通指针一样:

  • 定义指针时,还没有确定指向哪个成员
  • 不初始化会是随机值,不安全
  • nullptr 表示:当前不指向任何成员

就是一个安全的初始空状态。

你真棒你应该也会了吧!我也学会啦!

相关推荐
沫璃染墨7 分钟前
《从零入门Linux系统篇(五十七):线程篇·十——生产者消费者模型进阶:从环形缓冲区到POSIX信号量》
linux·运维·服务器·开发语言·c++·系统架构·信号处理
wuminyu19 分钟前
LockStack在虚拟线程Mount和Unmount拷贝过程剖析
java·linux·c语言·jvm·c++
Logic10143 分钟前
C语言/数据结构排序题解:三个数的最大乘积——排序后比较两种候选情况
c语言·数据结构·数组·排序·时间复杂度·算法题·负数处理
知识分享小能手1 小时前
C++ 学习教程,从入门到精通,string类和标准模板库 — 完整知识点详解(16)
开发语言·c++·学习
无忧.芙桃1 小时前
位图妙用:512MB 实现 40 亿整数的存在性查询
c语言·c++·面试·哈希算法
ShineWinsu1 小时前
对于Redis:Steam、Geospatial、Hyperloglog、Bitmap、Bitfield类型的解析
数据库·c++·redis·分布式·缓存·面试·zset
朝朝辞暮i1 小时前
C++ 第 31C 课:Subscriber 到底是什么
开发语言·c++·算法
殷色玫瑰2 小时前
C++ string类详解:常用接口、字符串操作与模拟实现
java·linux·c语言·开发语言·数据结构·c++
李游Leo2 小时前
HarmonyOS 7 + Spatial Recon Kit-C++:3DGS 高斯参数的非有限值隔离与可渲染性门禁【鸿蒙心迹】
开发语言·c++·3d·harmonyos
Evand J2 小时前
【MATLAB例程】三维RRT+APF路径规划与AOA-TDOA融合定位算法。附代码的下载链接
算法·matlab·路径规划·rrt·tdoa·apf·aoa