<p>C++中指针符号“”属于类型而非变量名,正确声明应为int a, b;,而int a, b;中仅a是指针、b是int型变量,易引发误解和错误。</p>

怎么写一个合法的 C++ 指针变量声明
指针不是“带星号的变量”,而是**类型的一部分**。写错位置,编译器立刻报错或语义完全跑偏。
常见错误现象:int* a, b; 你以为 b 也是指针?其实只有 a 是,b 是普通 —— 因为 <code>* 绑定的是变量名,不是类型名。
- 正确写法(推荐):
int* a;或更清晰的int *a;(*紧贴变量名,强调它属于这个变量) - 多个指针必须分开写:
int *a, *b, *c; - 别用
typedef或using隐藏指针性,初学时反而增加理解负担 - 声明后务必初始化,否则是野指针:
int *p = nullptr;比int *p;安全得多
为什么 nullptr 比 NULL 或 0 更可靠
本质是类型安全问题。NULL 在老标准里常定义为 0 或 ((void*)0),传入函数重载时可能意外匹配到 int 版本而非指针版本。
使用场景:所有需要“空地址”的地方,包括函数参数、返回值、成员初始化。
立即学习“C++免费学习笔记(深入)”;
- 函数重载歧义示例:
void f(int); void f(char*); f(NULL);可能调f(int);但f(nullptr)一定调f(char*) -
nullptr是字面量,类型为std::nullptr_t,可隐式转成任意指针类型,但不会转成整数 - C++11 起必须用
nullptr;旧代码里的NULL建议逐步替换
解引用前不检查是否为空,程序大概率崩溃
对 nullptr 或已释放内存的指针执行 *p,行为未定义——多数情况直接 Segmentation fault,调试时栈回溯往往不指向出问题那行,而是更下游。
常见错误现象:程序在某次输入后崩,但崩的位置和指针使用位置隔了几个函数调用。
- 每次解引用前加判断:
if (p != nullptr) { ... *p ... } - 更稳妥的做法是用智能指针(如
std::unique_ptr),但初学阶段先练手动检查习惯 - 注意:
delete p;后p仍非nullptr,是悬垂指针;删完应立即置空:delete p; p = nullptr; - 数组指针别用
delete,要用delete[];混用会触发未定义行为,且不一定当场暴露
指针和数组名在函数参数里“自动退化”容易误判
写 void f(int arr[10]),编译器实际当成 void f(int* arr) —— 方括号里的数字被忽略,sizeof(arr) 得到的是指针大小(通常是 8),不是数组大小。
这导致新手常以为能用 sizeof 算出传入数组长度,结果逻辑全错。
- 函数内无法仅凭参数获知原始数组长度;必须额外传参,如
void f(int* arr, size_t len) - 想保留长度信息,改用
std::array或std::vector;它们是真正带尺寸的对象 - 全局或局部定义的数组(非参数)可用
sizeof(arr)/sizeof(arr[0]),但一进函数就失效 - 字符串字面量如
"hello"类型是const char[6],传入函数也退化为const char*
指针本身不难,难的是每一步操作都依赖上下文:它指向哪、有没有权限访问、生命周期是否还有效。这些没法靠语法检查发现,得靠写的时候多问一句“这个地址现在归谁管”。










