4

我明白了POD的含义,并且我知道当我在 C++ 中将结构声明为

struct f {};

有一个默认构造函数、一个默认复制构造函数、一个默认析构函数等。(如果我理解正确的话)

我的问题是:如何在没有隐式构造函数/析构函数/等的情况下仅使用普通数据(如 4 个 int 值)声明 POD 结构。

我错过了什么?

4

4 回答 4

7

每个对象类型都有一个构造函数——否则你将如何构造它?——还有一个析构函数——否则它会如何被销毁?它们不会“妨碍”任何事情,因为在仅 POD 字段的情况下,默认实现是无操作的,就像您说的那样:

struct f {
    f() {}
    ~f() {}
    int a, b, c, d;
};

但是,如果您编写一个空的构造函数,则该类型将变为非 POD。C++11 通过默认解决了这个问题:

f() = default;
~f() = default;

复制构造函数的情况略有不同,其中隐式生成的构造函数只是为 POD 类型做“正确的事情”的一种便利:

f(const f& other) : a(other.a), b(other.b), c(other.c), d(other.d) {}

没有理由自己重写。如果要使类型不可复制,可以将复制构造函数标记为已删除f(const f&) = delete;或声明它private

同样重要的是要注意成员函数不像成员变量那样存储在对象上。您可以将 aclassstruct同时视为两件事:

  1. 数据布局的描述

  2. 包含用于操作该数据的函数和类型的命名空间

面向对象编程的 C++ 模型只是将这两件事结合在一个地方。

于 2012-10-19T17:44:37.360 回答
5

如何在没有隐式构造函数/析构函数/等的情况下使用纯数据(如 4 个 int 值)声明 POD 结构。

像这样:

struct f {
  int i1, i2, i3, i4;
};

编译器生成的构造函数不会妨碍它成为 POD。

9类[类]

10) POD struct 109是一个非联合类,它既是普通类又是标准布局类,并且没有非 POD 结构、非 POD 联合(或此类类型的数组)类型的非静态数据成员)。类似地,POD 联合是一个既是普通类又是标准布局类的联合,并且没有非 POD 结构、非 POD 联合(或此类类型的数组)类型的非静态数据成员。POD 类是一个 POD 结构或 POD 联合的类。

所以,它必须是

a) 普通类和
b) 标准布局类。

如下所述:

7) 标准布局类是这样的类:
— 没有非标准布局类(或此类类型的数组)或引用类型的非静态数据成员,
— 没有虚函数 (10.3) 和虚基类(10.1),
——对所有非静态数据成员具有相同的访问控制(第 11 条),
——没有非标准布局的基类,
——要么在最派生类中没有非静态数据成员,要么在大多数具有
非静态数据成员的基类,或者没有具有非静态数据成员的基类,并且
- 没有与第一个非静态数据成员相同类型的基类。

6) [...] 普通类是具有普通默认构造函数 (12.1) 并且可轻松复制的类

详述于:

12.1 构造函数 [class.ctor]

5) [...]如果默认构造函数不是用户提供的,并且如果:
- 它的类没有虚拟函数 (10.3) 和虚拟基类 (10.1),并且
- 没有非静态数据成员它的类有一个大括号或相等初始化器,并且
——它的类的所有直接基类都有普通的默认构造函数,并且
——对于它的类的所有非静态数据成员,它们是类类型(或其数组) ,每个这样的类都有一个简单的默认构造函数。

由于上述所有条件均适用,因此该类是 POD。

于 2012-10-19T17:43:52.453 回答
2

首先,所有这些隐式成员函数仅在概念上存在。在您实际尝试使用它们之前,它们不会真正影响任何东西。这意味着,如果您不希望他们这样做,他们不应该“妨碍”。

其次,非虚成员函数(无论是否显式声明)对类的数据布局没有影响。即他们在这方面没有“妨碍”(如果这就是你的意思)。

于 2012-10-19T17:42:53.110 回答
1

是的,POD 的定义明确排除了隐式生成的特殊成员函数。如果您指定其中之一与默认生成的完全相同:您的类型不再是 POD。在 C++11 中,这个问题是用default关键字解决的。

有了这一切,POD 的定义(通常)与 C 代码中的定义相同:

struct X { int a, b, c, d; };
于 2012-10-19T17:40:34.850 回答