关于嵌套结构体POD特性的疑问:GCC 7.3.1判定结果存疑
为什么结构体A会被判定为POD类型?
哎,我一眼就发现问题所在了——你混淆了嵌套类型定义和成员变量!你的代码里,struct B只是在A内部定义的一个类型,根本不是A的成员变量!所以结构体A的成员只有int i这一个纯POD类型,完全符合POD的判定标准,自然std::is_pod<A>::value返回true(输出1);而A::B因为包含std::string这种非POD类型,所以被判定为非POD(输出0),合起来就是你看到的“10”。
先拆解你的代码结构
你写的代码其实等价于:
struct A { int i; // 这才是A的唯一成员 struct B { std::string s; }; // 这只是在A内部声明了一个新类型,不是成员变量 };
如果你的本意是让B成为A的成员变量,那得改成这样:
struct A { int i; struct B { std::string s; } b; // 这里的b才是A的成员变量 };
或者先定义B再作为成员:
struct B { std::string s; }; struct A { int i; B b; // 明确声明B类型的成员变量 };
这时候再去判断,std::is_pod<A>::value就会返回false了,因为A包含了非POD类型的成员。
再说说POD判定的核心标准(C++11及以后)
一个类型要被判定为POD,得同时满足两个要求:
- 是平凡类型:拥有平凡的默认构造/析构、拷贝/移动函数,没有虚函数或虚基类
- 是标准布局类型:所有非静态成员访问控制一致,没有虚函数/虚基类,没有非标准布局的基类等
你的原始A类型,成员只有int i,完美符合这两个条件,所以是POD;而A::B因为包含std::string(非平凡、非标准布局),所以肯定不是POD。
关于你提到的内存分配场景
如果是你原始的代码版本,用malloc分配A的空间是完全没问题的——因为A本身就是POD,和嵌套的B类型半毛钱关系都没有。但如果是你误以为的“B是A的成员”的情况,那确实不能用malloc,因为非POD类型需要调用构造函数来初始化内部的成员(比如std::string需要初始化它的内部缓冲区)。
所以GCC7.3.1的行为完全符合C++标准,不是bug,问题出在你对代码结构的误解上哦。
内容的提问来源于stack exchange,提问作者acensored
相关产品推荐
相关产品推荐

