当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《C++中的POD类型是什么?》经验,为你挑选了7个好方法。

我有几次遇到这个术语POD型.这是什么意思?



1> Greg Hewgill..:

POD代表普通旧数据 - 即没有构造函数,析构函数和虚拟成员函数的类(无论是使用关键字struct还是关键字定义class).维基百科关于POD的文章更详细,并将其定义为:

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

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


POD类型具有非POD类型不具有的特征.例如,如果你有一个global,const,POD类型的结构,你可以用括号表示法初始化它的内容,它被放入只读内存,并且不需要生成代码来初始化它(构造函数或其他),因为它是程序图像的一部分.这对于经常对RAM,ROM或Flash有严格限制的嵌入式人员非常重要.
在C++ 11中,您可以执行std :: is_pod ()来判断MyType是否为POD.
有区别.内在类型是"内置"语言原语.POD类型是这些,以及这些(和其他POD)的聚合.
Bjarne Stroustrup的[关于C++性能的技术报告](http://www.stroustrup.com/performanceTR.pdf)指出,C++标准将POD描述为"_a数据类型,它与布局中C中的等效数据类型兼容,初始化,以及使用memcpy_"复制它的能力".也许应该区分POD类型和POD结构.
** - 1**截至2016年8月16日,这个答案仍然存在根本错误和误导:POD类型不限于类类型.
@Greg Hewgill:为什么我们需要区分POD和非POD?
@Cale C中没有“字符串”类型。有一个“ char *”,但最重要的区别是,尽管类型本身实际上是POD类型,但其概念值却是概念性的,即您的想法它代表的是字符数组-出于您的原因,不是POD。实际的指针本身(即您传递的`char *`)基本上是化装的整数,并且在判断某物是否为POD类型时,其用途与`int`相同。但是,要复制它表示的_conceptual string_,是的,您需要做更多的事情。

2> Steve Jessop..:

非正式地:

POD是一种类型(包括类),其中C++编译器保证结构中不会出现"魔术":例如,隐藏指向vtable的指针,在转换为其他类型时应用于地址的偏移量(至少如果目标的POD也是如此),构造函数或析构函数.粗略地说,类型是POD,当它中的唯一内容是内置类型和它们的组合时.结果是"像C"一样的行为.

不那么非正式:

int,char,wchar_t,bool,float,double是豆荚,因为是long/shortsigned/unsigned他们的版本.

指针(包括指向函数的指针和指向成员的指针)是POD,

enums 是POD

一个constvolatile POD是POD.

一个class,structunion荚果的是一个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类型"

9(4): "POD-struct是一个聚合类,它没有非POD-struct类型的非静态数据成员,非POD-union(或这类类型的数组)或引用,并且没有用户 -定义复制操作符,没有用户定义的析构函数.类似地,POD-union是一个聚合联合,它没有非POD-struct,非POD-union(或这类类型的数组)或引用类型的非静态数据成员,并且没有用户定义的复制操作符,也没有用户定义的析构函数.

8.5.1(1): "聚合是一个数组或类(第9节),没有用户声明的构造函数(12.1),没有私有或受保护的非静态数据成员(第11节),没有基类(第10节)没有虚拟功能(10.3)."


如果维基百科错了......不应该编辑吗?
@Lazer:这是另一个问题,"POD如何表现?" 而不是"POD是什么意思?".总之,差异与初始化有关(因此也使用memcpy复制对象),与该编译器的C结构布局兼容,以及指针向上和向下转换.POD"就像C类型",非POD不保证这样做.因此,如果您希望您的类型可以像C结构一样移植,那么您必须确保它是POD,因此您需要知道其中的差异.
@muntoo:一直以来,我一直在评论引用维基百科过时信息的答案.我想,我可以编辑那个答案,但如果我四处编辑其他人的回答同意我的意见,我会觉得麻烦,无论我认为我是多么正确.
你有正式/不正式的.你可以添加经验法则.内置类型和内置类型的聚合(或类似的东西).除了获得确切的定义之外,我们还需要使知识易于使用.

3> ugasoft..:

普通旧数据

总之,它是所有内置数据类型(例如int,char,float,long,unsigned char,double POD的数据,等等)和所有聚集.是的,这是一个递归定义.;)

更清楚一点,POD就是我们所说的"结构":一个单元或一组只存储数据的单元.


确实,我们有时称它们为"结构".但是,我们总是错误的,因为结构不一定是POD类型.
显然......结构和类几乎是等价的,但在"业务"中我们称'结构'是一个简单的数据收集器,通常没有ctors和dtor,通常具有值语义...
对我来说,使C++与class关键字相同或接近于C++是错误的:struct只添加对类的公共默认访问.我更容易制作类似C的结构,我们在c ++的第0天会有POD.

4> набиячлэвэли..:

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

要建造,

要被摧毁

有自定义运营商.

一定不能有虚函数

并且不得覆盖运营商.

如何检查某些东西是否是POD?好吧,有一个结构称为std::is_pod:

namespace std {
// Could use is_standard_layout && is_trivial instead of the builtin.
template
  struct is_pod
  : public integral_constant
  { };
}

(来自header type_traits)


参考:

http://en.cppreference.com/w/cpp/types/is_pod

http://en.wikipedia.org/wiki/Plain_old_data_structure

http://en.wikipedia.org/wiki/Plain_Old_C++_Object

文件type_traits


Incorrect, a POD type may have member functions or overloaded operators. (But it may not have virtual member functions.)

5> amitabes..:

POD(普通旧数据)对象具有以下数据类型之一 - 基本类型,指针,联合,结构,数组或类 - 没有构造函数.相反,非POD对象是构造函数所在的对象.POD对象在获得具有适当大小的存储的类型时开始其生命周期,并且当对象的存储被重用或取消分配时,其生命周期结束.

PlainOldData类型也不能包含以下任何内容:

虚函数(自己的或继承的)

虚拟基类(直接或间接).

PlainOldData的更宽松定义包括具有构造函数的对象; 但不包括虚拟的东西.PlainOldData类型的重要问题是它们是非多态的.可以使用POD类型进行继承,但是只应该对ImplementationInheritance(代码重用)而不是多态/子类型进行继承.

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



6> Ciro Santill..:

static_assert从C++ 11到C++ 17和POD效果的所有非POD案例的例子

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

std::is_pod将按照/sf/ask/17360801/中的说明从C++ 20中删除,让我们在支持到达替换时更新它.

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

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 
#include 
#include 

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(), "");
                    static_assert(!std::is_trivial(), "");
                    static_assert(!std::is_pod(), "");
                }

                // 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(), "");
                    static_assert(!std::is_trivial(), "");
                    static_assert(!std::is_pod(), "");
                }
            }

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

        // 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(), "");
                    static_assert(!std::is_pod(), "");
                }

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

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

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

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

            // 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(), "");
                    static_assert(!std::is_pod(), "");
                }

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

                // 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(), "");
                    static_assert(std::is_pod(), "");
                }
            }

            // 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(), "");
                //static_assert(!std::is_pod(), "");
            };

            // 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(), "");
                    //static_assert(!std::is_pod(), "");
                }

                // 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(), "");
                    static_assert(!std::is_pod(), "");
                }

                // 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(), "");
            static_assert(std::is_pod(), "");
        }

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

        // Private member: became POD in C++11
        // /sf/ask/17360801/#4762944
        {
            struct C {
                private:
                    int i;
            };
#if __cplusplus >= 201103L
            static_assert(std::is_pod(), "");
#else
            static_assert(!std::is_pod(), "");
#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.
        // /sf/ask/17360801/
        {
            static_assert(!std::is_pod>(), "");
            static_assert(!std::is_trivially_copyable>(), "");
            // Some might be though:
            // /sf/ask/17360801/
            static_assert(std::is_pod>(), "");
        }
    }

    // # 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:
    // /sf/ask/17360801/#4178176
    {
        struct Pod {
            uint32_t i;
            uint64_t j;
        };
        static_assert(std::is_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(), "");

        // __attribute__((packed)) only works for POD, and is ignored for non-POD, and emits a warning
        // /sf/ask/17360801/#52986680
        {
            struct C {
                int i;
            };

            struct D : C {
                int j;
            };

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

            static_assert(std::is_pod(), "");
            static_assert(!std::is_pod(), "");
            static_assert(!std::is_pod(), "");
        }
    }
#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上.



7> plugwash..:

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

C ++作为C的扩展而开始其生命。尽管现代C ++不再是C的严格超集,但人们仍然期望两者之间具有高度的兼容性。

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

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

    布局必须与相应的C类型相同。

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

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

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

用户定义的副本构造函数,移动构造函数,副本分配和析构函数对参数传递和返回有影响。许多C ABI在寄存器中传递并返回较小的参数,但是传递给用户定义的构造函数/辅助函数/析构函数的引用只能与内存位置一起使用。

因此,需要定义哪些类型可以期望是“ C兼容的”,哪些类型不能。在这方面,C ++ 03有点过分严格,任何用户定义的构造函数都将禁用内置的构造函数,并且任何将它们添加回去的尝试都将导致它们是用户定义的,因此类型为非Pod。通过允许用户重新引入内置构造函数,C ++ 11大大提高了性能。

推荐阅读
帆侮听我悄悄说星星
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有