1. 指针到底是什么?从内存寻址说起
很多C++新手一听到“指针”两个字就头疼,觉得它抽象、难懂,还容易出错。其实,指针并没有那么神秘。你可以把它想象成现实世界中的“门牌号”。假设你住在一个巨大的小区(内存)里,你家(某个变量)的具体位置,比如“幸福路888号”,这个地址就是指针所保存的东西。指针本身不存储你家里的家具(数据),它只记录你家的地址。
计算机的内存就像一条非常非常长的街道,每间房子(内存单元)都有一个独一无二的编号,这个编号就是内存地址。当我们创建一个变量,比如 int age = 25;,系统就会在内存这条街上找一间空房子,把25这个值放进去,并且给这间房子贴上一个地址标签。指针变量,比如 int* ptr = &age;,它的工作就是把这个地址标签(&age 获取到的地址)抄写下来,保存好。
我刚开始学的时候,总把 * 和 & 搞混。这里有个简单的记忆窍门:& 是“取地址符”,它的工作是“找门牌号”。你把它放在一个变量前面,它就告诉你这个变量住在哪里。而 * 是“解引用符”,它的工作是“按图索骥”。你把它放在一个指针前面,它就根据指针记录的门牌号,去那个地址的房子里把东西取出来或者放进去。所以,ptr 保存的是地址,*ptr 操作的是地址里存放的那个整数值。
理解这一点至关重要:指针的值是一个地址,指针的类型决定了从这个地址开始,要解读多少字节的数据。一个 int* 指针和 char* 指针可能保存着相同的地址值,但当你用 * 去操作时,前者会读取4个字节(通常)并解释为一个整数,后者只会读取1个字节并解释为一个字符。这就好比同一个仓库坐标,如果把它当作粮仓,你会运出成吨的粮食;如果把它当作金库,你会取出金条。坐标没变,但解读方式决定了你拿到的是什么。
2. 指针在内存中占多大地方?空指针与野指针的致命陷阱
2.1 指针的大小:与类型无关,与系统架构有关
一个非常常见的问题是:指向 int 的指针和指向 double 的指针,谁更大?答案是:一样大。这有点反直觉,但仔细想想就明白了。指针的本质是存放一个内存地址,地址就是一个编号。这个编号的长度(需要多少位二进制来存储)取决于你的计算机能管理多大的内存空间,也就是系统的寻址能力。
在32位操作系统上,内存地址用32位二进制数表示,所以一个地址需要4个字节来存储。因此,无论它是指向 char、int 还是复杂的数据结构,任何类型的指针在32位系统下都占4个字节。同理,在64位系统下,地址是64位的,所以指针占8个字节。你可以用 sizeof(int*) 或 sizeof(任何类型*) 来验证这一点。记住这个结论,能帮你避免很多关于指针内存占用的困惑。
2.2 空指针:安全的“初始化”状态
刚声明一个指针变量时,它里面存放的地址值是随机的、未定义的,指向哪里完全不知道。直接使用这样的指针非常危险。因此,一个好的编程习惯是:在定义指针时,如果暂时不知道让它指向哪里,就立即将其初始化为空指针。
在C++中,空指针表示“不指向任何对象”。过去我们用 NULL(实际上是0)来表示,现代C++(C++11以后)更推荐使用关键字 nullptr。int* ptr = nullptr; 这行代码明确告诉所有人,也告诉编译器,这个指针现在是空的、无效的。
空指针的核心规则是:你可以安全地检查一个指针是否为空,但绝不能试图通过空指针去访问内存。if (ptr != nullptr) 这样的判断是安全的,但 *ptr = 100; 如果 ptr 是空指针,程序一定会崩溃(访问违规)。这就像你有一个写着“地址不存在”的纸条,你不能凭着这张纸条去某个地方取东西。
2.3 野指针:程序崩溃的“头号杀手”
比空指针更可怕的是“野指针”。野指针指的是指向非法内存区域的指针。它通常由两种情况产生:
- 指针未初始化:前面提到的,声明后没赋值就使用。
- 指针所指内存已被释放:这是新手和老手都极易踩中的大坑。
int* p = new int(42); // 在堆上分配内存,p指向这块内存
delete p;


243

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



