문제

나는 POD 유형이라는 용어를 몇 번 접했습니다.무슨 뜻이에요?

도움이 되었습니까?

해결책

현물 상환 지불 의지합니다 평범한 오래된 데이터 - 즉, 클래스 (키워드로 정의하든 struct 또는 키워드 class) 생성자가 없으면 파괴자 및 가상 회원 기능이 기능합니다. 포드에 관한 Wikipedia의 기사 좀 더 자세히 설명하고 다음과 같이 정의합니다.

C ++의 일반 기존 데이터 구조는 멤버로서 POD 만 포함하는 집계 클래스이며, 사용자 정의 파괴자, 사용자 정의 사본 할당 연산자 및 포인터 투 인원 유형의 비 종합 멤버가 없습니다.

더 자세한 내용은 찾을 수 있습니다 C ++ 98/03에 대한이 답변. C ++ 11은 포드를 둘러싼 규칙을 변경하여 크게 긴장을 풀었습니다. 후속 답변이 필요합니다.

다른 팁

매우 비공식적으로:

POD는 C++ 컴파일러가 구조에서 "마법"이 발생하지 않음을 보장하는 유형(클래스 포함)입니다.예를 들어 vtable에 대한 숨겨진 포인터, 다른 유형(적어도 대상의 POD인 경우), 생성자 또는 소멸자로 캐스팅될 때 주소에 적용되는 오프셋입니다.대략적으로 말하자면, 그 안에 있는 유일한 항목이 내장된 유형과 이들의 조합인 경우 유형은 POD입니다.결과는 C 유형처럼 "작동"하는 것입니다.

덜 비공식적으로:

  • int, char, wchar_t, bool, float, double POD도 마찬가지입니다. long/short 그리고 signed/unsigned 그들의 버전.
  • 포인터(함수에 대한 포인터 및 멤버에 대한 포인터 포함)는 POD입니다.
  • enums POD입니다
  • const 또는 volatile POD는 POD입니다.
  • class, struct 또는 union POD는 모든 비정적 데이터 멤버가 있는 경우 POD입니다. public, 이며 기본 클래스도 없고 생성자, 소멸자 또는 가상 메서드도 없습니다.정적 멤버는 이 규칙에 따라 무언가가 POD가 되는 것을 중단하지 않습니다.이 규칙은 C++11에서 변경되었으며 특정 전용 멤버가 허용됩니다. 모든 비공개 멤버로 구성된 클래스가 POD 클래스가 될 수 있나요?
  • Wikipedia에서는 POD가 포인터-멤버 유형의 멤버를 가질 수 없다고 말하는 것이 잘못되었습니다.또는 오히려 C++98 표현에는 맞지만 TC1은 멤버에 대한 포인터가 POD임을 명시했습니다.

공식적으로(C++03 표준):

3.9(10): "산술 유형(3.9.1), 열거형 유형, 포인터 유형, 멤버 유형에 대한 포인터(3.9.2) 및 이러한 유형의 cv 한정 버전(3.9.3)은 집합적으로 호출자 스칼라 유형입니다.스칼라 유형, POD-struct 유형, POD-union 유형(9절), 이러한 유형의 배열 및 이러한 유형의 cv 정규 버전(3.9.3)을 집합적으로 POD 유형이라고 합니다.

9(4): "POD-struct는 비POD-struct, 비POD-union(또는 그러한 유형의 배열) 또는 참조 유형의 비정적 데이터 멤버가 없고 사용자 정의 복사 연산자가 없는 집계 클래스입니다. 사용자 정의 소멸자.마찬가지로 POD-union은 비POD-struct, 비-POD-union(또는 이러한 유형의 배열) 또는 참조 유형의 비정적 데이터 멤버가 없고 사용자 정의 복사 연산자가 없는 집계 Union입니다. 사용자 정의 소멸자.

8.5.1(1): "집계체는 사용자 선언 생성자(12.1), 전용 또는 보호된 비정적 데이터 멤버(11절), 기본 클래스(10절) 및 가상 함수(10.3)가 없는 배열 또는 클래스(9절)입니다. ."

평범한 오래된 데이터

요컨대, 그것은 모든 내장 데이터 유형입니다 (예 : int, char, float, long, unsigned char, double, 등) 및 POD 데이터의 모든 응집. 예, 그것은 재귀 적 정의입니다. ;)

더 명확하게 말하면, 포드는 우리가 "구조물"이라고 부르는 것입니다. 단위 또는 데이터를 저장하는 단위 그룹.

POD (PlainoldData)를 이해하는 것처럼 원시 데이터 일뿐입니다. 필요하지 않습니다.

  • 건설하려면
  • 파괴 되려면
  • 사용자 정의 연산자가 있습니다.
  • 가상 기능이 없어야합니다.
  • 운영자를 무시해서는 안됩니다.

포드인지 확인하는 방법? 글쎄, 그에 대한 구조물이 있습니다 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)>
  { };
}

(Header type_traits에서)


참조:

POD (일반 이전 데이터) 객체에는 이러한 데이터 유형 중 하나 (기본 유형, 포인터, 유니온, 구조, 배열 또는 클래스)가 있습니다. 반대로, 비 POD 객체는 생성자가 존재하는 개체입니다. 포드 객체는 유형에 맞는 적절한 크기의 스토리지를 얻을 때 수명을 시작하고 물체의 저장소가 재사용되거나 거래 될 때 수명이 끝납니다.

PlainOldData 유형은 다음과 같은 것이 없어야합니다.

  • 가상 함수 (자체 또는 상속)
  • 가상 기본 클래스 (직접 또는 간접).

PlainoldData의 느슨한 정의에는 생성자가있는 객체가 포함됩니다. 그러나 가상이있는 사람들을 제외합니다. PlainoldData 유형의 중요한 문제는 비 폴리 모르 픽이라는 것입니다. 상속은 POD 유형으로 수행 할 수 있지만, 다형성/하위 유형이 아닌 구현 단위 (코드 재사용)를 위해서만 수행해야합니다.

일반적인 (엄격히 정확하지는 않지만) 정의는 PlainoldData 유형이 veetable이없는 것이라는 것입니다.

모든 비 POD 사례의 예 static_assert C ++ 11에서 C ++ 17 및 POD 효과까지

std::is_pod C ++ 11에 추가되었으므로 현재 표준을 고려해 봅시다.

std::is_pod 언급 된대로 C ++ 20에서 제거됩니다. https://stackoverflow.com/a/48435532/895245 , 대체에 대한 지원이 도착하면서 이것을 업데이트합시다.

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 ++ Testsuite 프로젝트를 확인하는 것이 게으르다. https://softwareengineering.stackexchange.com/questions/199708/is-there-a-complience-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

우분투 18.04, GCC 8.2.0.

포드의 개념과 유형 특성 std::is_pod C ++ 20에서는 더 이상 사용되지 않습니다. 보다 이것 자세한 내용은 질문입니다.

POD와 POD가 아닌 것을 구별해야 하는 이유는 무엇입니까?

C++는 C의 확장으로 시작되었습니다.최신 C++는 더 이상 C의 엄격한 상위 집합이 아니지만 사람들은 여전히 ​​둘 사이의 높은 수준의 호환성을 기대합니다.

대략적으로 말하면, POD 유형은 C와 호환되는 유형이며 아마도 마찬가지로 중요한 것은 특정 ABI 최적화와 호환되는 유형입니다.

C와 호환되려면 두 가지 제약 조건을 충족해야 합니다.

  1. 레이아웃은 해당 C 유형과 동일해야 합니다.
  2. 유형은 해당 C 유형과 동일한 방식으로 함수에 전달되고 함수에서 반환되어야 합니다.

특정 C++ 기능은 이와 호환되지 않습니다.

가상 메서드를 사용하려면 컴파일러가 C에 존재하지 않는 가상 메서드 테이블에 하나 이상의 포인터를 삽입해야 합니다.

사용자 정의 복사 생성자, 이동 생성자, 복사 할당 및 소멸자는 매개변수 전달 및 반환에 영향을 미칩니다.많은 C ABI는 레지스터에서 작은 매개변수를 전달하고 반환하지만 사용자 정의 생성자/할당/소멸자에 전달된 참조는 메모리 위치에서만 작동할 수 있습니다.

따라서 "C 호환"이 가능한 유형과 그렇지 않은 유형을 정의할 필요가 있습니다.C++03은 이와 관련하여 다소 지나치게 엄격했습니다.C++11은 많은 것을 열어주었습니다.

C ++를 사용하면 일반 기존 데이터가 int, char 등과 같은 것이 사용 된 유일한 유형이라는 것을 의미하지는 않습니다. 평범한 오래된 데이터는 실제로 실제로 한 위치에서 메모리의 한 위치에서 다른 위치로 가져갈 수 있다는 것을 의미하며, 예상대로 일이 예상대로 작동합니다 (즉, 날려 버리지 않음). 수업 또는 수업에 포함 된 클래스가 포함 된 경우, 포인터 또는 참조 또는 가상 기능이있는 클래스가있는 경우에도 끊어집니다. 기본적으로 포인터가 어딘가에 참여해야한다면 일반적인 오래된 데이터가 아닙니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top