C++ 数组与指针:新手最容易踩的 3 个坑
2026/8/21大约 2 分钟
C++ 数组与指针:新手最容易踩的 3 个坑
学 C++ 的时候,指针和数组永远是绕不开的两兄弟。它们看起来长得一样,用起来却处处是坑。这篇文章把我踩过的三个坑记下来,希望能帮你少走点弯路。
坑一:数组名到底是不是指针?
很多人背口诀:数组名就是首地址。这句话不全对,它只在"作为函数参数"时成立。
#include <iostream>
void func(int arr[]) {
// 这里的 arr 已经退化成指针了
std::cout << sizeof(arr) << std::endl; // 8,是一个指针的大小
}
int main() {
int a[5] = {1, 2, 3, 4, 5};
std::cout << sizeof(a) << std::endl; // 20,整个数组的大小
func(a);
return 0;
}同样的 a,在 main 里 sizeof 是 20(5 个 int),传进函数后就变成了 8(一个指针)。因为参数传参时数组名会退化为指针,这就是数组和指针"看起来一样"的真相。
坑二:越界访问不报错,但会悄悄改坏数据
C++ 不像某些语言会检查数组边界。越界访问不会立刻报错,它只是读/写了一块"别人的内存",等到程序崩溃时,你根本不知道是哪里出的问题。
int data[3] = {10, 20, 30};
for (int i = 0; i <= 3; i++) { // 注意是 <= 3,越界了!
std::cout << data[i] << std::endl; // i=3 时读的是 data 之外的内存
}这个 bug 的可怕之处在于:它可能跑一万次才崩一次,而且崩溃的位置和真正的错误位置毫不相干。所以写循环的时候,边界条件一定要反复确认。
坑三:指针指向了"已经死掉"的变量
函数返回局部变量的地址,是新手必踩的经典陷阱:
int *bad() {
int local = 42;
return &local; // 危险!函数返回后 local 就没了
}
int main() {
int *p = bad();
std::cout << *p << std::endl; // 可能打印 42,也可能打印垃圾值
return 0;
}local 是栈上的局部变量,函数一返回它就被销毁了。返回它的地址,就是拿着一把指向"废墟"的钥匙。编译器甚至会给出警告:function returns address of local variable。
正确的做法是让数据活得更久:
- 用
new在堆上分配(但要记得delete,或者直接用std::unique_ptr) - 或者把数据放在调用方,传指针进来让函数去填
小结
- 数组名只有传参时才退化成指针
- 越界不报错,所以要自己管好边界
- 永远不要返回局部变量的地址
指针不难,难的是脑子里时刻有一张"这块内存在哪、什么时候被释放"的地图。这张图建起来,C++ 的大门就真正打开了。
💬 评论区