0

根据(2003)标准对结构的定义,它是类的特殊情况,对成员、函数和基类具有不同的默认访问修饰符。它还继续将结构的要求定义为 POD 结构。

C++ 2003 标准,ISO 14882 第 9.0.4 节:

结构是使用类键结构定义的类;它的成员和基类(第 10 条)默认是公共的(第 11 条)。联合是使用类键联合定义的类;默认情况下,它的成员是公共的,并且一次只保存一个数据成员(9.5)。[注:类类型的聚合在 8.5.1 中描述。] POD-struct 是一个聚合类,它没有非 POD-struct、非 POD-union(或此类类型的数组)或引用类型的非静态数据成员,并且没有用户定义的复制赋值运算符和没有用户定义的析构函数。类似地,POD 联合是一个聚合联合,它没有非 POD 结构、非 POD 联合(或此类类型的数组)或引用类型的非静态数据成员,并且没有用户定义的复制赋值运算符,也没有用户定义的析构函数。

鉴于此定义,非 POD 结构和类之间的唯一区别因素是默认访问修饰符。

这是我可以想象的拥有非 POD 结构的目的:

  • 它们是一个遗留功能,需要维护以实现向后兼容性
  • 打字public:很难。

当其他系统假定它们是 POD 时,拥有非 POD 结构可能会导致痛苦,例如当传递给 C 并返回时。举例来说,当另一个开发人员更新假定为 POD 的结构以使其不再是 POD 时,此人遇到了问题。因为默认情况下编译器不会静态断言 POD 特性,所以当在只能使用 POD 结构的上下文中使用该结构时,应用程序将在运行时崩溃。更糟糕的是,我可以想象(虽然我不确定这是否可能)一个非 POD 结构在需要 POD 的某些情况下工作,而在其他情况下失败,导致错误和崩溃,这简直是难以忍受追查。

鉴于在某些情况下,非 POD 结构会导致奇怪和破坏行为的领域,非 POD 结构有什么用?为什么不在编译时静态检查结构的 POD 特性(通过 C++11 中的 std::is_pod 或 Boost 等效项)?

4

2 回答 2

4

我认为这是一个毫无意义的历史事故,坦率地说,这个class关键字根本不应该在 C++ 中添加。那好吧!

如果 astruct必须是 POD,这通常会很烦人——你通常会从 POD 开始,仅仅因为你可以称它为“结构”,然后当你以后不得不在许多地方更改它时决定使它成为非 POD。

请注意,GCC(至少直到最近)并不关心您是否(转发)在一个地方将某些东西声明为类,而在其他地方声明为结构,反之亦然。Clang 抱怨这种事情(因为它完全有权这样做,尽管这确实“破坏”了一些现有代码)。

于 2012-02-24T01:56:14.770 回答
0

“默认情况下,编译器不会静态断言 POD-ness”

哦?

#include <iostream>         // std::cout, std::endl
#include <type_traits>      // std::is_pod
#include <string>           // std::string, std::to_string
using namespace std;

struct A
{
    int x;
};

struct B
{
    string s;
};

int main()
{
    static bool const a = is_pod<A>::value;
    static_assert( a, "Ah..." );
    static_assert( !is_pod<B>::value, "Bah!" );
}

struct允许非 POD的原因,例如B上面,即为什么语言是这样设计的,可能可以在 Bjarne Stroustrup 的《C++ 的设计和演变》一书中找到。如果不是,那么可能只有 Bjarne 自己知道。因为这种 C++ 通用性struct从一开始就存在。

于 2012-02-24T02:05:16.323 回答