结构体指针在c++中需注意类型名使用、内存分配安全、成员访问语法及资源管理:mystruct*可直接声明;new需判空或捕获异常;访问用->;裸指针不管理资源,推荐std::unique_ptr或raii封装。

结构体定义后,指针声明必须带 struct 关键字(C 风格)或使用类型别名
在纯 C++ 中,如果结构体是用 struct MyStruct { ... }; 定义的,那么 MyStruct 本身就是一个类型名,可以直接写 MyStruct* ptr;。但如果你沿用 C 风格写法:struct MyStruct { ... }; 而没加 typedef,又在 C++ 里混用 C 头文件或旧代码,就可能遇到 error: 'MyStruct' does not name a type——这是因为编译器只认 struct MyStruct,不单独认 MyStruct。
解决方法很直接:
- 推荐写法:定义时顺便“提升”为类型名,比如
struct MyStruct { int x; };之后,MyStruct* p = new MyStruct;就合法 - 兼容旧 C 代码:显式写
struct MyStruct* p; - 更干净的方案:用
using MyStructPtr = MyStruct*;或typedef MyStruct* MyStructPtr;,后续可读性更强
new 分配结构体指针时,记得检查是否为空(尤其在嵌入式或低内存环境)
new 在分配失败时会抛出 std::bad_alloc 异常(默认行为),但若用了 new(std::nothrow),就会返回 nullptr。很多初学者直接写 MyStruct* p = new MyStruct; 然后马上解引用,一旦内存不足就崩。
稳妥做法:
- 默认异常模式下,用
try/catch捕获std::bad_alloc - 用 nothrow 版本时,必须判空:
MyStruct* p = new(std::nothrow) MyStruct(); if (!p) { /* 处理失败 */ } - 现代 C++ 更建议用
std::unique_ptr<mystruct></mystruct>,自动管理且默认抛异常,不用手动判空
指向结构体的指针访问成员,用 -> 而不是 .,但容易和智能指针混淆
原生指针 MyStruct* p 访问成员必须用 p->x,这是语法硬性要求;写成 p.x 会报错 error: request for member 'x' in 'p', which is of pointer type。但换成 std::shared_ptr<mystruct></mystruct> 或 std::unique_ptr<mystruct></mystruct>,虽然底层也是指针语义,但重载了 operator->,所以同样用 ptr->x —— 表面一致,实际机制不同。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
注意点:
- 不要对空指针调用
->,否则未定义行为(多半 crash) -
std::unique_ptr和原生指针一样,ptr.get()才拿到裸指针,ptr.get()->x是冗余写法 - 结构体有 const 成员或构造函数时,
new MyStruct{...}初始化比默认构造后赋值更安全
结构体内含指针成员时,指向它的指针本身不负责深拷贝
定义 struct BufHolder { char* data; size_t len; };,再声明 BufHolder* p = new BufHolder{new char[100], 100}; —— 这时 p 只管 BufHolder 对象本身的内存,p->data 指向的堆内存得你手动 delete[]。如果把 p 拷贝给另一个指针 BufHolder* q = p;,两个指针共用同一块 data,析构时容易 double-free。
真正要小心的是:
- 原生指针不做任何生命周期管理,深拷贝/移动语义全靠手写
- 用
std::vector<char></char>替代char*成员,能自动处理内存 - 若必须用裸指针成员,至少把结构体封装成 RAII 类,构造分配、析构释放
结构体指针看着简单,但一牵扯到资源管理,裸指针的“自由”很快变成责任。别图省事跳过初始化或忽略所有权归属。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










