C++ 中的 POD 类型是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/146452/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 13:12:58  来源:igfitidea点击:

What are POD types in C++?

c++typesc++-faq

提问by paxos1977

I've come across this term POD-type a few times.
What does it mean?

我多次遇到过这个术语 POD 类型。
这是什么意思?

采纳答案by Greg Hewgill

PODstands for Plain Old Data- that is, a class (whether defined with the keyword structor the keyword class) without constructors, destructors and virtual members functions. Wikipedia's article on PODgoes into a bit more detail and defines it as:

POD代表Plain Old Data——即一个没有构造函数、析构函数和虚成员函数的类(无论是用关键字struct还是关键字定义class)。维基百科关于 POD 的文章更详细一些,并将其定义为:

A Plain Old Data Structure in C++ is an aggregate class that contains only PODS as members, has no user-defined destructor, no user-defined copy assignment operator, and no nonstatic members of pointer-to-member type.

C++ 中的普通旧数据结构是一个聚合类,它只包含 PODS 作为成员,没有用户定义的析构函数,没有用户定义的复制赋值运算符,也没有成员指针类型的非静态成员。

Greater detail can be found in this answer for C++98/03. C++11 changed the rules surrounding POD, relaxing them greatly, thus necessitating a follow-up answer here.

更多细节可以在C++98/03 的答案中找到。C++11 改变了围绕 POD 的规则,大大放宽了它们,因此需要在此处进行后续回答

回答by Steve Jessop

Very informally:

非常非正式:

A POD is a type (including classes) where the C++ compiler guarantees that there will be no "magic" going on in the structure: for example hidden pointers to vtables, offsets that get applied to the address when it is cast to other types (at least if the target's POD too), constructors, or destructors. Roughly speaking, a type is a POD when the only things in it are built-in types and combinations of them. The result is something that "acts like" a C type.

POD 是一种类型(包括类),其中 C++ 编译器保证结构中不会发生“魔法”:例如,指向 vtable 的隐藏指针、在地址转换为其他类型时应用于地址的偏移量(至少如果目标的 POD 也是)、构造函数或析构函数。粗略地说,当一个类型中只有内置类型和它们的组合时,它就是一个 POD。结果是“表现得像”C 类型的东西。

Less informally:

不那么非正式:

  • int, char, wchar_t, bool, float, doubleare PODs, as are long/shortand signed/unsignedversions of them.
  • pointers (including pointer-to-function and pointer-to-member) are PODs,
  • enumsare PODs
  • a constor volatilePOD is a POD.
  • a class, structor unionof PODs is a POD provided that all non-static data members are public, and it has no base class and no constructors, destructors, or virtual methods. Static members don't stop something being a POD under this rule. This rule has changed in C++11 and certain private members are allowed: Can a class with all private members be a POD class?
  • Wikipedia is wrong to say that a POD cannot have members of type pointer-to-member. Or rather, it's correct for the C++98 wording, but TC1 made explicit that pointers-to-member are POD.
  • intcharwchar_tboolfloatdouble是 POD,long/short以及signed/unsigned它们的版本。
  • 指针(包括指向函数的指针和指向成员的指针)是 POD,
  • enums是 POD
  • aconstvolatilePOD 是 POD。
  • 一个classstructunion荚果的是一个POD条件是所有的非静态数据成员是public,它没有基类和没有构造,析构函数,或虚拟方法。在此规则下,静态成员不会阻止某物成为 POD。此规则在 C++11 中已更改,并且允许某些私有成员:具有所有私有成员的类可以是 POD 类吗?
  • 维基百科说 POD 不能有成员指针类型的成员是错误的。或者更确切地说,它对于 C++98 的措辞是正确的,但是 TC1 明确指出指向成员的指针是 POD。

Formally (C++03 Standard):

正式(C++03 标准):

3.9(10):"Arithmetic types (3.9.1), enumeration types, pointer types, and pointer to member types (3.9.2) and cv-qualified versions of these types (3.9.3) are collectively caller scalar types. Scalar types, POD-struct types, POD-union types (clause 9), arrays of such types and cv-qualified versions of these types (3.9.3) are collectively called POD types"

9(4):"A POD-struct is an aggregate class that has no non-static data members of type non-POD-struct, non-POD-union (or array of such types) or reference, and has no user-define copy operator and no user-defined destructor. Similarly a POD-union is an aggregate union that has no non-static data members of type non-POD-struct, non-POD-union (or array of such types) or reference, and has no user-define copy operator and no user-defined destructor.

8.5.1(1):"An aggregate is an array or class (clause 9) with no user-declared constructors (12.1), no private or protected non-static data members (clause 11), no base classes (clause 10) and no virtual functions (10.3)."

3.9(10):“算术类型 (3.9.1)、枚举类型、指针类型和成员类型指针 (3.9.2) 以及这些类型的 cv 限定版本 (3.9.3) 统称为调用者标量类型。标量类型、POD 结构类型、POD 联合类型(第 9 条)、此类类型的数组以及这些类型的 cv 限定版本(3.9.3)统称为 POD 类型”

9(4):“POD 结构是一个聚合类,它没有非 POD 结构、非 POD 联合(或此类类型的数组)或引用类型的非静态数据成员,并且没有用户-定义复制操作符,没有用户定义的析构函数。类似地,POD 联合是一个聚合联合,它没有非 POD 结构、非 POD 联合(或此类类型的数组)或引用类型的非静态数据成员,并且没有用户定义的复制操作符和用户定义的析构函数。

8.5.1(1):“聚合是一个数组或类(第 9 条),没有用户声明的构造函数(12.1),没有私有或受保护的非静态数据成员(第 11 条),没有基类(第 10 条)并且没有虚函数(10.3)。”

回答by ugasoft

Plain Old Data

普通旧数据

In short, it is all built-in data types (e.g. int, char, float, long, unsigned char, double, etc.) and all aggregation of POD data. Yes, it's a recursive definition. ;)

总之,它是所有内置的数据类型(例如intcharfloatlongunsigned chardoublePOD的数据,等等)和所有聚集。是的,这是一个递归定义。;)

To be more clear, a POD is what we call "a struct": a unit or a group of units that just store data.

更明确地说,一个 POD 就是我们所说的“结构”:一个或一组只存储数据的单元。

回答by набиячлэвэли

As I understand POD (PlainOldData) is just a raw data - it does not need:

据我了解,POD(PlainOldData)只是一个原始数据 - 它不需要:

  • to be constructed,
  • to be destroyed,
  • to have custom operators.
  • Must not have virtual functions,
  • and must not override operators.
  • 待建设,
  • 被摧毁,
  • 有自定义运算符。
  • 不能有虚函数,
  • 并且不得覆盖运算符。

How to check if something is a POD? Well, there is a struct for that called std::is_pod:

如何检查某物是否是 POD?嗯,有一个结构叫做std::is_pod

namespace std {
// Could use is_standard_layout && is_trivial instead of the builtin.
template<typename _Tp>
  struct is_pod
  : public integral_constant<bool, __is_pod(_Tp)>
  { };
}

(From header type_traits)

(来自标题 type_traits)


Reference:


参考:

回答by amitabes

A POD (plain old data) object has one of these data types--a fundamental type, pointer, union, struct, array, or class--with no constructor. Conversely, a non-POD object is one for which a constructor exists. A POD object begins its lifetime when it obtains storage with the proper size for its type and its lifetime ends when the storage for the object is either reused or deallocated.

POD(纯旧数据)对象具有这些数据类型之一——基本类型、指针、联合、结构、数组或类——没有构造函数。相反,非 POD 对象是存在构造函数的对象。当 POD 对象获得适合其类型大小的存储时,它的生命周期开始,当对象的存储被重用或解除分配时,它的生命周期结束。

PlainOldData types also must not have any of:

PlainOldData 类型也不得具有以下任何一项:

  • Virtual functions (either their own, or inherited)
  • Virtual base classes (direct or indirect).
  • 虚函数(它们自己的或继承的)
  • 虚拟基类(直接或间接)。

A looser definition of PlainOldData includes objects with constructors; but excludes those with virtual anything. The important issue with PlainOldData types is that they are non-polymorphic. Inheritance can be done with POD types, however it should only be done for ImplementationInheritance (code reuse) and not polymorphism/subtyping.

PlainOldData 的宽松定义包括具有构造函数的对象;但排除那些具有虚拟任何东西的人。PlainOldData 类型的重要问题是它们是非多态的。继承可以用 POD 类型来完成,但是它应该只用于 ImplementationInheritance(代码重用)而不是多态/子类型。

A common (though not strictly correct) definition is that a PlainOldData type is anything that doesn't have a VeeTable.

一个常见的(虽然不是严格正确的)定义是,PlainOldData 类型是任何没有 VeeTable 的东西。

回答by plugwash

Why do we need to differentiate between POD's and non-POD's at all?

为什么我们需要区分 POD 和非 POD?

C++ started its life as an extension of C. While modern C++ is no longer a strict superset of C, people still expect a high level of compatibility between the two.

C++ 最初是作为 C 的扩展而诞生的。虽然现代 C++ 不再是 C 的严格超集,但人们仍然期望两者之间具有高度的兼容性。

Roughly speaking, a POD type is a type that is compatible with C and perhaps equally importantly is compatible with certain ABI optimisations.

粗略地说,POD 类型是一种与 C 兼容的类型,也许同样重要的是与某些 ABI 优化兼容。

To be compatible with C, we need to satisfy two constraints.

为了与 C 兼容,我们需要满足两个约束。

  1. The layout must be the same as the corresponding C type.
  2. The type must be passed to and returned from functions in the same way as the corresponding C type.
  1. 布局必须与对应的 C 类型相同。
  2. 类型必须以与相应的 C 类型相同的方式传递给函数和从函数返回。

Certain C++ features are incompatible with this.

某些 C++ 功能与此不兼容。

Virtual methods require the compiler to insert one or more pointers to virtual method tables, something that doesn't exist in C.

虚方法要求编译器插入一个或多个指向虚方法表的指针,这在 C 中是不存在的。

User-defined copy constructors, move constructors, copy assignments and destructors have implications for parameter passing and returning. Many C ABIs pass and return small parameters in registers, but the references passed to the user defined constructor/assigment/destructor can only work with memory locations.

用户定义的复制构造函数、移动构造函数、复制赋值和析构函数对参数传递和返回有影响。许多 C ABI 在寄存器中传递和返回小参数,但传递给用户定义的构造函数/赋值/析构函数的引用只能使用内存位置。

So there is a need to define what types can be expected to be "C compatible" and what types cannot. C++03 was somewhat over-strict in this regard, any user-defined constructor would disable the built-in constructors and any attempt to add them back in would result in them being user-defined and hence the type being non-pod. C++11 opened things up quite a bit, by allowing the user to re-introduce the built-in constructors.

因此需要定义哪些类型可以预期为“C 兼容”,哪些类型不能。C++03 在这方面有点过于严格,任何用户定义的构造函数都会禁用内置构造函数,任何尝试将它们添加回来都会导致它们是用户定义的,因此类型是非 pod。通过允许用户重新引入内置构造函数,C++11 开放了很多东西。

回答by ThomasMcLeod

The concept of POD and the type trait std::is_podwill be deprecated in C++20. See thisquestion for further information.

POD 的概念和类型特征std::is_pod将在 C++20 中被弃用。有关更多信息,请参阅问题。

回答by Mark Kegel

With C++, Plain Old Data doesn't just mean that things like int, char, etc are the only types used. Plain Old Data really means in practice that you can take a struct memcpy it from one location in memory to another and things will work exactly like you would expect (i.e. not blow up). This breaks if your class, or any class your class contains, has as a member that is a pointer or a reference or a class that has a virtual function. Essentially, if pointers have to be involved somewhere, its not Plain Old Data.

对于 C++,Plain Old Data 不仅仅意味着 int、char 等是唯一使用的类型。普通旧数据实际上意味着在实践中您可以将 struct memcpy 从内存中的一个位置带到另一个位置,并且事情将完全按照您的预期工作(即不会爆炸)。如果您的类或您的类包含的任何类具有作为指针或引用或具有虚函数的类的成员,则这会中断。本质上,如果某个地方必须涉及指针,它不是普通的旧数据。