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

发布于 2024-07-05 14:06:39 字数 39 浏览 8 评论 0原文

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

眼眸印温柔 2024-07-12 14:06:39

从 C++11 到 C++17 具有 static_assert 的所有非 POD 案例以及 POD 效果的示例

已添加 std::is_pod在 C++11 中,所以现在让我们考虑该标准。

std::is_pod 已被弃用 C++20,如 https://stackoverflow.com/a 中所述/48435532/895245,让我们在更换的支持到来时更新此内容。

随着标准的发展,POD 限制变得越来越宽松,我的目标是通过 ifdefs 涵盖示例中的所有放松。

libstdc++ 在以下位置进行了少量测试: https://github.com/gcc-mirror/gcc/blob/gcc-8_2_0-release/libstdc%2B%2B-v3/testsuite/20_util/is_pod/value.cc 但它太少了。 维护者:如果您阅读本文,请合并此内容。 我懒得查看以下提到的所有 C++ 测试套件项目: https://softwareengineering.stackexchange.com/questions/199708/is-there-a-compliance-test-for-c-compilers

#include <type_traits>
#include <array>
#include <vector>

int main() {
#if __cplusplus >= 201103L
    // # Not POD
    //
    // Non-POD examples. Let's just walk all non-recursive non-POD branches of cppreference.
    {
        // Non-trivial implies non-POD.
        // https://en.cppreference.com/w/cpp/named_req/TrivialType
        {
            // Has one or more default constructors, all of which are either
            // trivial or deleted, and at least one of which is not deleted.
            {
                // Not trivial because we removed the default constructor
                // by using our own custom non-default constructor.
                {
                    struct C {
                        C(int) {}
                    };
                    static_assert(std::is_trivially_copyable<C>(), "");
                    static_assert(!std::is_trivial<C>(), "");
                    static_assert(!std::is_pod<C>(), "");
                }

                // No, this is not a default trivial constructor either:
                // https://en.cppreference.com/w/cpp/language/default_constructor
                //
                // The constructor is not user-provided (i.e., is implicitly-defined or
                // defaulted on its first declaration)
                {
                    struct C {
                        C() {}
                    };
                    static_assert(std::is_trivially_copyable<C>(), "");
                    static_assert(!std::is_trivial<C>(), "");
                    static_assert(!std::is_pod<C>(), "");
                }
            }

            // Not trivial because not trivially copyable.
            {
                struct C {
                    C(C&) {}
                };
                static_assert(!std::is_trivially_copyable<C>(), "");
                static_assert(!std::is_trivial<C>(), "");
                static_assert(!std::is_pod<C>(), "");
            }
        }

        // Non-standard layout implies non-POD.
        // https://en.cppreference.com/w/cpp/named_req/StandardLayoutType
        {
            // Non static members with different access control.
            {
                // i is public and j is private.
                {
                    struct C {
                        public:
                            int i;
                        private:
                            int j;
                    };
                    static_assert(!std::is_standard_layout<C>(), "");
                    static_assert(!std::is_pod<C>(), "");
                }

                // These have the same access control.
                {
                    struct C {
                        private:
                            int i;
                            int j;
                    };
                    static_assert(std::is_standard_layout<C>(), "");
                    static_assert(std::is_pod<C>(), "");

                    struct D {
                        public:
                            int i;
                            int j;
                    };
                    static_assert(std::is_standard_layout<D>(), "");
                    static_assert(std::is_pod<D>(), "");
                }
            }

            // Virtual function.
            {
                struct C {
                    virtual void f() = 0;
                };
                static_assert(!std::is_standard_layout<C>(), "");
                static_assert(!std::is_pod<C>(), "");
            }

            // Non-static member that is reference.
            {
                struct C {
                    int &i;
                };
                static_assert(!std::is_standard_layout<C>(), "");
                static_assert(!std::is_pod<C>(), "");
            }

            // Neither:
            //
            // - has no base classes with non-static data members, or
            // - has no non-static data members in the most derived class
            //   and at most one base class with non-static data members
            {
                // Non POD because has two base classes with non-static data members.
                {
                    struct Base1 {
                        int i;
                    };
                    struct Base2 {
                        int j;
                    };
                    struct C : Base1, Base2 {};
                    static_assert(!std::is_standard_layout<C>(), "");
                    static_assert(!std::is_pod<C>(), "");
                }

                // POD: has just one base class with non-static member.
                {
                    struct Base1 {
                        int i;
                    };
                    struct C : Base1 {};
                    static_assert(std::is_standard_layout<C>(), "");
                    static_assert(std::is_pod<C>(), "");
                }

                // Just one base class with non-static member: Base1, Base2 has none.
                {
                    struct Base1 {
                        int i;
                    };
                    struct Base2 {};
                    struct C : Base1, Base2 {};
                    static_assert(std::is_standard_layout<C>(), "");
                    static_assert(std::is_pod<C>(), "");
                }
            }

            // Base classes of the same type as the first non-static data member.
            // TODO failing on GCC 8.1 -std=c++11, 14 and 17.
            {
                struct C {};
                struct D : C {
                    C c;
                };
                //static_assert(!std::is_standard_layout<C>(), "");
                //static_assert(!std::is_pod<C>(), "");
            };

            // C++14 standard layout new rules, yay!
            {
                // Has two (possibly indirect) base class subobjects of the same type.
                // Here C has two base classes which are indirectly "Base".
                //
                // TODO failing on GCC 8.1 -std=c++11, 14 and 17.
                // even though the example was copy pasted from cppreference.
                {
                    struct Q {};
                    struct S : Q { };
                    struct T : Q { };
                    struct U : S, T { };  // not a standard-layout class: two base class subobjects of type Q
                    //static_assert(!std::is_standard_layout<U>(), "");
                    //static_assert(!std::is_pod<U>(), "");
                }

                // Has all non-static data members and bit-fields declared in the same class
                // (either all in the derived or all in some base).
                {
                    struct Base { int i; };
                    struct Middle : Base {};
                    struct C : Middle { int j; };
                    static_assert(!std::is_standard_layout<C>(), "");
                    static_assert(!std::is_pod<C>(), "");
                }

                // None of the base class subobjects has the same type as
                // for non-union types, as the first non-static data member
                //
                // TODO: similar to the C++11 for which we could not make a proper example,
                // but with recursivity added.

                // TODO come up with an example that is POD in C++14 but not in C++11.
            }
        }
    }

    // # POD
    //
    // POD examples. Everything that does not fall neatly in the non-POD examples.
    {
        // Can't get more POD than this.
        {
            struct C {};
            static_assert(std::is_pod<C>(), "");
            static_assert(std::is_pod<int>(), "");
        }

        // Array of POD is POD.
        {
            struct C {};
            static_assert(std::is_pod<C>(), "");
            static_assert(std::is_pod<C[]>(), "");
        }

        // Private member: became POD in C++11
        // https://stackoverflow.com/questions/4762788/can-a-class-with-all-private-members-be-a-pod-class/4762944#4762944
        {
            struct C {
                private:
                    int i;
            };
#if __cplusplus >= 201103L
            static_assert(std::is_pod<C>(), "");
#else
            static_assert(!std::is_pod<C>(), "");
#endif
        }

        // Most standard library containers are not POD because they are not trivial,
        // which can be seen directly from their interface definition in the standard.
        // https://stackoverflow.com/questions/27165436/pod-implications-for-a-struct-which-holds-an-standard-library-container
        {
            static_assert(!std::is_pod<std::vector<int>>(), "");
            static_assert(!std::is_trivially_copyable<std::vector<int>>(), "");
            // Some might be though:
            // https://stackoverflow.com/questions/3674247/is-stdarrayt-s-guaranteed-to-be-pod-if-t-is-pod
            static_assert(std::is_pod<std::array<int, 1>>(), "");
        }
    }

    // # POD effects
    //
    // Now let's verify what effects does PODness have.
    //
    // Note that this is not easy to do automatically, since many of the
    // failures are undefined behaviour.
    //
    // A good initial list can be found at:
    // https://stackoverflow.com/questions/4178175/what-are-aggregates-and-pods-and-how-why-are-they-special/4178176#4178176
    {
        struct Pod {
            uint32_t i;
            uint64_t j;
        };
        static_assert(std::is_pod<Pod>(), "");

        struct NotPod {
            NotPod(uint32_t i, uint64_t j) : i(i), j(j) {}
            uint32_t i;
            uint64_t j;
        };
        static_assert(!std::is_pod<NotPod>(), "");

        // __attribute__((packed)) only works for POD, and is ignored for non-POD, and emits a warning
        // https://stackoverflow.com/questions/35152877/ignoring-packed-attribute-because-of-unpacked-non-pod-field/52986680#52986680
        {
            struct C {
                int i;
            };

            struct D : C {
                int j;
            };

            struct E {
                D d;
            } /*__attribute__((packed))*/;

            static_assert(std::is_pod<C>(), "");
            static_assert(!std::is_pod<D>(), "");
            static_assert(!std::is_pod<E>(), "");
        }
    }
#endif
}

GitHub 上游

测试环境:

for std in 11 14 17; do echo $std; g++-8 -Wall -Werror -Wextra -pedantic -std=c++$std pod.cpp; done

Ubuntu 18.04、GCC 8.2.0。

Examples of all non-POD cases with static_assert from C++11 to C++17 and POD effects

std::is_pod has been added in C++11, so let's consider that standard onwards for now.

std::is_pod has been deprecated C++20 as mentioned at https://stackoverflow.com/a/48435532/895245 , let's update this as support arrives for the replacements.

POD restrictions have become more and more relaxed as the standard evolved, I aim to cover all relaxations in the example through ifdefs.

libstdc++ has at tiny bit of testing at: https://github.com/gcc-mirror/gcc/blob/gcc-8_2_0-release/libstdc%2B%2B-v3/testsuite/20_util/is_pod/value.cc but it just too little. Maintainers: please merge this if you read this post. I'm lazy to check out all the C++ testsuite projects mentioned at: https://softwareengineering.stackexchange.com/questions/199708/is-there-a-compliance-test-for-c-compilers

#include <type_traits>
#include <array>
#include <vector>

int main() {
#if __cplusplus >= 201103L
    // # Not POD
    //
    // Non-POD examples. Let's just walk all non-recursive non-POD branches of cppreference.
    {
        // Non-trivial implies non-POD.
        // https://en.cppreference.com/w/cpp/named_req/TrivialType
        {
            // Has one or more default constructors, all of which are either
            // trivial or deleted, and at least one of which is not deleted.
            {
                // Not trivial because we removed the default constructor
                // by using our own custom non-default constructor.
                {
                    struct C {
                        C(int) {}
                    };
                    static_assert(std::is_trivially_copyable<C>(), "");
                    static_assert(!std::is_trivial<C>(), "");
                    static_assert(!std::is_pod<C>(), "");
                }

                // No, this is not a default trivial constructor either:
                // https://en.cppreference.com/w/cpp/language/default_constructor
                //
                // The constructor is not user-provided (i.e., is implicitly-defined or
                // defaulted on its first declaration)
                {
                    struct C {
                        C() {}
                    };
                    static_assert(std::is_trivially_copyable<C>(), "");
                    static_assert(!std::is_trivial<C>(), "");
                    static_assert(!std::is_pod<C>(), "");
                }
            }

            // Not trivial because not trivially copyable.
            {
                struct C {
                    C(C&) {}
                };
                static_assert(!std::is_trivially_copyable<C>(), "");
                static_assert(!std::is_trivial<C>(), "");
                static_assert(!std::is_pod<C>(), "");
            }
        }

        // Non-standard layout implies non-POD.
        // https://en.cppreference.com/w/cpp/named_req/StandardLayoutType
        {
            // Non static members with different access control.
            {
                // i is public and j is private.
                {
                    struct C {
                        public:
                            int i;
                        private:
                            int j;
                    };
                    static_assert(!std::is_standard_layout<C>(), "");
                    static_assert(!std::is_pod<C>(), "");
                }

                // These have the same access control.
                {
                    struct C {
                        private:
                            int i;
                            int j;
                    };
                    static_assert(std::is_standard_layout<C>(), "");
                    static_assert(std::is_pod<C>(), "");

                    struct D {
                        public:
                            int i;
                            int j;
                    };
                    static_assert(std::is_standard_layout<D>(), "");
                    static_assert(std::is_pod<D>(), "");
                }
            }

            // Virtual function.
            {
                struct C {
                    virtual void f() = 0;
                };
                static_assert(!std::is_standard_layout<C>(), "");
                static_assert(!std::is_pod<C>(), "");
            }

            // Non-static member that is reference.
            {
                struct C {
                    int &i;
                };
                static_assert(!std::is_standard_layout<C>(), "");
                static_assert(!std::is_pod<C>(), "");
            }

            // Neither:
            //
            // - has no base classes with non-static data members, or
            // - has no non-static data members in the most derived class
            //   and at most one base class with non-static data members
            {
                // Non POD because has two base classes with non-static data members.
                {
                    struct Base1 {
                        int i;
                    };
                    struct Base2 {
                        int j;
                    };
                    struct C : Base1, Base2 {};
                    static_assert(!std::is_standard_layout<C>(), "");
                    static_assert(!std::is_pod<C>(), "");
                }

                // POD: has just one base class with non-static member.
                {
                    struct Base1 {
                        int i;
                    };
                    struct C : Base1 {};
                    static_assert(std::is_standard_layout<C>(), "");
                    static_assert(std::is_pod<C>(), "");
                }

                // Just one base class with non-static member: Base1, Base2 has none.
                {
                    struct Base1 {
                        int i;
                    };
                    struct Base2 {};
                    struct C : Base1, Base2 {};
                    static_assert(std::is_standard_layout<C>(), "");
                    static_assert(std::is_pod<C>(), "");
                }
            }

            // Base classes of the same type as the first non-static data member.
            // TODO failing on GCC 8.1 -std=c++11, 14 and 17.
            {
                struct C {};
                struct D : C {
                    C c;
                };
                //static_assert(!std::is_standard_layout<C>(), "");
                //static_assert(!std::is_pod<C>(), "");
            };

            // C++14 standard layout new rules, yay!
            {
                // Has two (possibly indirect) base class subobjects of the same type.
                // Here C has two base classes which are indirectly "Base".
                //
                // TODO failing on GCC 8.1 -std=c++11, 14 and 17.
                // even though the example was copy pasted from cppreference.
                {
                    struct Q {};
                    struct S : Q { };
                    struct T : Q { };
                    struct U : S, T { };  // not a standard-layout class: two base class subobjects of type Q
                    //static_assert(!std::is_standard_layout<U>(), "");
                    //static_assert(!std::is_pod<U>(), "");
                }

                // Has all non-static data members and bit-fields declared in the same class
                // (either all in the derived or all in some base).
                {
                    struct Base { int i; };
                    struct Middle : Base {};
                    struct C : Middle { int j; };
                    static_assert(!std::is_standard_layout<C>(), "");
                    static_assert(!std::is_pod<C>(), "");
                }

                // None of the base class subobjects has the same type as
                // for non-union types, as the first non-static data member
                //
                // TODO: similar to the C++11 for which we could not make a proper example,
                // but with recursivity added.

                // TODO come up with an example that is POD in C++14 but not in C++11.
            }
        }
    }

    // # POD
    //
    // POD examples. Everything that does not fall neatly in the non-POD examples.
    {
        // Can't get more POD than this.
        {
            struct C {};
            static_assert(std::is_pod<C>(), "");
            static_assert(std::is_pod<int>(), "");
        }

        // Array of POD is POD.
        {
            struct C {};
            static_assert(std::is_pod<C>(), "");
            static_assert(std::is_pod<C[]>(), "");
        }

        // Private member: became POD in C++11
        // https://stackoverflow.com/questions/4762788/can-a-class-with-all-private-members-be-a-pod-class/4762944#4762944
        {
            struct C {
                private:
                    int i;
            };
#if __cplusplus >= 201103L
            static_assert(std::is_pod<C>(), "");
#else
            static_assert(!std::is_pod<C>(), "");
#endif
        }

        // Most standard library containers are not POD because they are not trivial,
        // which can be seen directly from their interface definition in the standard.
        // https://stackoverflow.com/questions/27165436/pod-implications-for-a-struct-which-holds-an-standard-library-container
        {
            static_assert(!std::is_pod<std::vector<int>>(), "");
            static_assert(!std::is_trivially_copyable<std::vector<int>>(), "");
            // Some might be though:
            // https://stackoverflow.com/questions/3674247/is-stdarrayt-s-guaranteed-to-be-pod-if-t-is-pod
            static_assert(std::is_pod<std::array<int, 1>>(), "");
        }
    }

    // # POD effects
    //
    // Now let's verify what effects does PODness have.
    //
    // Note that this is not easy to do automatically, since many of the
    // failures are undefined behaviour.
    //
    // A good initial list can be found at:
    // https://stackoverflow.com/questions/4178175/what-are-aggregates-and-pods-and-how-why-are-they-special/4178176#4178176
    {
        struct Pod {
            uint32_t i;
            uint64_t j;
        };
        static_assert(std::is_pod<Pod>(), "");

        struct NotPod {
            NotPod(uint32_t i, uint64_t j) : i(i), j(j) {}
            uint32_t i;
            uint64_t j;
        };
        static_assert(!std::is_pod<NotPod>(), "");

        // __attribute__((packed)) only works for POD, and is ignored for non-POD, and emits a warning
        // https://stackoverflow.com/questions/35152877/ignoring-packed-attribute-because-of-unpacked-non-pod-field/52986680#52986680
        {
            struct C {
                int i;
            };

            struct D : C {
                int j;
            };

            struct E {
                D d;
            } /*__attribute__((packed))*/;

            static_assert(std::is_pod<C>(), "");
            static_assert(!std::is_pod<D>(), "");
            static_assert(!std::is_pod<E>(), "");
        }
    }
#endif
}

GitHub upstream.

Tested with:

for std in 11 14 17; do echo $std; g++-8 -Wall -Werror -Wextra -pedantic -std=c++$std pod.cpp; done

on Ubuntu 18.04, GCC 8.2.0.

倥絔 2024-07-12 14:06:39

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

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

更多详细信息可以在C++98/03 的答案中找到。 C++11 改变了 POD 周围的规则,大大放宽了它们,因此需要在此处提供后续答案

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

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.

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.

唐婉 2024-07-12 14:06:39

非常通俗地说:

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

不太非正式的:

  • intcharwchar_tboolfloatdouble 是 POD,它们的长/短有符号/无符号 版本也是如此。
  • 指针(包括函数指针和成员指针)是 POD,
  • enum 是 POD,
  • const易失性 POD 是 POD 。
  • POD 的 classstructunion 是一个 POD,前提是所有非静态数据成员都是 public,它没有基类,也没有构造函数、析构函数或虚方法。 在此规则下,静态成员不会阻止某些内容成为 POD。 此规则在 C++11 中已更改,并且允许某些私有成员: 一个包含所有私有成员的类可以是 POD 类吗?
  • 维基百科说 POD 不能具有指向成员的指针类型的成员是错误的。 或者更确切地说,它对于 C++98 措辞是正确的,但 TC1 明确指出指向成员的指针是 POD。

形式上(C++03 标准):

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

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

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

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.

Less informally:

  • int, char, wchar_t, bool, float, double are PODs, as are long/short and signed/unsigned versions of them.
  • pointers (including pointer-to-function and pointer-to-member) are PODs,
  • enums are PODs
  • a const or volatile POD is a POD.
  • a class, struct or union of 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.

Formally (C++03 Standard):

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)."

定格我的天空 2024-07-12 14:06:39

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

C++ 最初是作为 C 的扩展而诞生的。虽然现代 C++ 不再是 C 的严格超集,但人们仍然期望两者之间具有高水平的兼容性。 平台的“C ABI”也经常充当该平台上其他语言的事实标准间语言 ABI。

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

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

  1. 布局必须与相应的 C 类型相同。
  2. 该类型必须以与相应的 C 类型相同的方式传递给函数并从函数返回。

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

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

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

因此需要定义哪些类型可以“C 兼容”,哪些类型不能。 C++03 在这方面有点过于严格,任何用户定义的构造函数都会禁用内置构造函数,并且任何将它们添加回来的尝试都会导致它们是用户定义的,因此类型是非 Pod 的。 C++11 通过允许用户重新引入内置构造函数,使事情变得更加开放。

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

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. The "C ABI" of a platform also frequently acts as a de-facto standard inter-language ABI for other languages on the platform.

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

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

  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.

Certain C++ features are incompatible with this.

Virtual methods require the compiler to insert one or more pointers to virtual method tables, something that doesn't exist in 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.

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.

橪书 2024-07-12 14:06:39

Plain Old Data

简而言之,都是内置数据类型(例如 int< /code>、char浮点long无符号字符双精度、等)以及 POD 数据的所有聚合。 是的,这是一个递归定义。 ;)

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

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. ;)

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

最单纯的乌龟 2024-07-12 14:06:39

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

  • 构建、
  • 销毁、
  • 自定义运算符。
  • 不得具有虚函数,
  • 并且不得覆盖运算符。

如何检查某物是否是 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)>
  { };
}

来自标头 type_traits)

参考:

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

  • 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:

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)

Reference:

对不⑦ 2024-07-12 14:06:39

POD 的概念和类型特征 std::is_pod 在 C++20 中已被弃用。 有关更多信息,请参阅为什么在 C++20 中不推荐使用 std::is_pod?

The concept of POD and the type trait std::is_pod has been deprecated in C++20. See Why is std::is_pod deprecated in C++20? for further information.

落花浅忆 2024-07-12 14:06:39

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

PlainOldData 类型也不得具有以下任何功能:

  • 虚拟函数(它们自己的或继承的)
  • 虚拟基类(直接或间接)。

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

一个常见的(尽管不是严格正确的)定义是 PlainOldData 类型是任何没有 VeeTable 的类型。

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.

PlainOldData types also must not have any of:

  • 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.

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

风尘浪孓 2024-07-12 14:06:39

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文