Các loại POD trong C ++ là gì?


978

Tôi đã gặp thuật ngữ này loại POD một vài lần.
Nó có nghĩa là gì?



5
vui lòng xem chat.stackoverflow.com/transcript/message/213026#213026 và các tin nhắn của ngày hôm sau để thảo luận về câu trả lời được chấp nhận
Johannes Schaub - litb


@ paxos1977: Vui lòng thay đổi lựa chọn "giải pháp" (câu trả lời hiện tại của Hewgill) để câu trả lời sai về cơ bản không đánh lừa những người làm việc ở đây.
Chúc mừng và hth. - Alf

Chúng tôi đã kết luận rằng chuỗi kiểu c KHÔNG phải là kiểu POD vì 1.) con trỏ không tiếp giáp với dữ liệu chuỗi và 2.) để tạo chuỗi kiểu POD, bạn sẽ cần đảm bảo kiểu có một char dài hạn trong phạm vi kích thước được xác định trước của loại POD, dẫn đến hành vi không xác định.

Câu trả lời:


694

POD là viết tắt của Plain Old Data - nghĩa là một lớp (cho dù được xác định bằng từ khóa structhoặc từ khóa class) mà không có hàm tạo, hàm hủy và hàm thành viên ảo. Bài viết của Wikipedia về POD đi sâu vào chi tiết hơn một chút và định nghĩa nó là:

Cấu trúc dữ liệu cũ đơn giản trong C ++ là một lớp tổng hợp chỉ chứa PODS là thành viên, không có hàm hủy do người dùng định nghĩa, không có toán tử gán sao chép do người dùng định nghĩa và không có thành viên không thuộc loại con trỏ thành thành viên.

Chi tiết hơn có thể được tìm thấy trong câu trả lời này cho C ++ 98/03 . C ++ 11 đã thay đổi các quy tắc xung quanh POD, giúp chúng thư giãn rất nhiều, do đó cần có câu trả lời tiếp theo ở đây .


34
Có một sự khác biệt. Các loại nội tại là các nguyên thủy ngôn ngữ "dựng sẵn". Các loại POD là những loại này, cộng với các tập hợp của chúng (và các POD khác).
Adam Wright

59
Các loại POD có các đặc điểm mà các loại không phải POD không có. Ví dụ: nếu bạn có cấu trúc kiểu POD toàn cầu, const, bạn có thể khởi tạo nội dung của nó bằng ký hiệu dấu ngoặc, nó được đưa vào bộ nhớ chỉ đọc và không cần tạo mã để khởi tạo nó (hàm tạo hoặc cách khác), bởi vì nó là một phần của hình ảnh chương trình Điều này rất quan trọng đối với những người nhúng thường có các ràng buộc chặt chẽ về RAM, ROM hoặc Flash.
Mike DeSimone

34
Trong C ++ 11, bạn có thể thực hiện std :: is_pod <MyType> () để cho biết MyType có phải là POD hay không.
allyourcode

7
Báo cáo kỹ thuật về hiệu suất C ++ của Bjarne Stroustrup nói rằng tiêu chuẩn C ++ mô tả POD là " kiểu dữ liệu tương thích với kiểu dữ liệu tương đương trong C trong bố cục, khởi tạo và khả năng được sao chép bằng memcpy ". Có lẽ nên phân biệt giữa loại POD và cấu trúc POD.
dùng34660

6
−1 Câu trả lời này về cơ bản vẫn sai & gây hiểu nhầm kể từ ngày 16 tháng 8 năm 2016: Các loại POD không bị hạn chế là các loại lớp.
Chúc mừng và hth. - Alf

352

Rất không chính thức:

POD là một loại (bao gồm các lớp) trong đó trình biên dịch C ++ đảm bảo rằng sẽ không có "phép thuật" nào xảy ra trong cấu trúc: ví dụ: các con trỏ ẩn cho vtables, offset được áp dụng cho địa chỉ khi nó được truyền sang các loại khác ( ít nhất là nếu POD của mục tiêu cũng vậy), các hàm tạo hoặc hàm hủy. Nói một cách đơn giản, một loại là một POD khi những thứ duy nhất trong đó là các loại tích hợp và kết hợp chúng. Kết quả là một cái gì đó "hoạt động như" một loại C.

Ít thông tin hơn:

  • int, char, wchar_t, bool, float, doubleLà PODs, cũng như long/shortsigned/unsignedcác phiên bản của họ.
  • con trỏ (bao gồm con trỏ đến chức năng và con trỏ đến thành viên) là PODs,
  • enums là POD
  • a consthoặc volatilePOD là POD.
  • a class, structhoặc unioncủa POD là một POD với điều kiện là tất cả các thành viên dữ liệu không tĩnh publicvà nó không có lớp cơ sở và không có hàm tạo, hàm hủy hoặc phương thức ảo. Các thành viên tĩnh không dừng một cái gì đó là POD theo quy tắc này. Quy tắc này đã thay đổi trong C ++ 11 và một số thành viên riêng được phép: Một lớp có tất cả các thành viên riêng có thể là lớp POD không?
  • Wikipedia đã sai khi nói rằng POD không thể có các thành viên thuộc loại con trỏ thành thành viên. Hay đúng hơn, nó đúng với từ ngữ C ++ 98, nhưng TC1 đã nói rõ rằng con trỏ thành viên là POD.

Chính thức (Tiêu chuẩn C ++ 03):

3.9 (10): "Các loại số học (3.9.1), các kiểu liệt kê, các loại con trỏ và con trỏ tới các loại thành viên (3.9.2) và các phiên bản đủ điều kiện cv của các loại này (3.9.3) là các kiểu vô hướng gọi chung. các loại, các loại cấu trúc POD, các loại kết hợp POD (điều 9), các mảng của các loại đó và các phiên bản đủ điều kiện cv của các loại này (3.9.3) được gọi chung là các loại POD "

9 (4): "POD-struct là một lớp tổng hợp không có thành viên dữ liệu không tĩnh thuộc loại không POD-struct, non-POD-union (hoặc mảng của các loại đó) hoặc không có người dùng- xác định toán tử sao chép và không có hàm hủy do người dùng định nghĩa. Tương tự, POD-union là một tập hợp tổng hợp không có thành viên dữ liệu không tĩnh thuộc loại không POD-struct, non-POD-union (hoặc mảng của các loại đó) hoặc tham chiếu, và không có toán tử sao chép do người dùng định nghĩa và không có hàm hủy do người dùng định nghĩa.

8.5.1 (1): "Tập hợp là một mảng hoặc lớp (mệnh đề 9) không có hàm tạo do người dùng khai báo (12.1), không có thành viên dữ liệu không tĩnh riêng tư hoặc được bảo vệ (mệnh đề 11), không có lớp cơ sở (mệnh đề 10) và không có chức năng ảo (10.3). "


3
Bạn có trang trọng / ít trang trọng. Bạn có thể thêm quy tắc của ngón tay cái. Được xây dựng trong các loại và tập hợp của các loại Được xây dựng (hoặc một cái gì đó tương tự). Ngoài ra để có được định nghĩa chính xác, chúng ta cần làm cho kiến ​​thức dễ sử dụng.
Martin York

1
Bạn hơi sai về bit "offset khi cast_to loại khác". Những độ lệch được áp dụng khi truyền tới lớp cơ sở hoặc lớp dẫn xuất. Vì vậy, nếu bạn chuyển từ một con trỏ lớp cơ sở POD sang một lớp dẫn xuất không phải POD, bạn vẫn có thể gặp phải một sự điều chỉnh.
MSalters

1
@Steve Jessop: Tại sao chúng ta cần phân biệt giữa POD và không phải POD?
Lazer

6
@Lazer: đó là một câu hỏi hoàn toàn khác, "PODs hành xử thế nào?" trái ngược với "POD có nghĩa là gì?". Tóm lại, sự khác biệt liên quan đến khởi tạo (do đó cũng sử dụng memcpy để sao chép các đối tượng), khả năng tương thích với bố cục cấu trúc C cho trình biên dịch đó và con trỏ lên và xuống. POD "hoạt động như loại C", không phải POD không được đảm bảo để làm như vậy. Vì vậy, nếu bạn muốn kiểu của mình hoạt động như một cấu trúc C, bạn phải đảm bảo rằng đó là POD, vì vậy bạn cần biết sự khác biệt.
Steve Jessop

4
@muntoo: nó đã được, thực sự tôi đã bình luận về câu trả lời trích dẫn thông tin lỗi thời từ Wikipedia. Tôi có thể chỉnh sửa câu trả lời đó, tôi cho rằng, nhưng tôi cảm thấy rắc rối nếu tôi đi xung quanh chỉnh sửa câu trả lời của người khác để đồng ý với tôi, bất kể tôi nghĩ tôi đúng như thế nào.
Steve Jessop

21

Dữ liệu cũ đơn giản

Nói tóm lại, đó là tất cả built-in các kiểu dữ liệu (ví dụ như int, char, float, long, unsigned char, double, vv) và tất cả các tập hợp dữ liệu POD. Vâng, đó là một định nghĩa đệ quy. ;)

Nói rõ hơn, POD là cái mà chúng ta gọi là "struct": một đơn vị hoặc một nhóm các đơn vị chỉ lưu trữ dữ liệu.


12
Đúng là đôi khi chúng ta gọi chúng là "một cấu trúc". Tuy nhiên, chúng tôi luôn sai khi làm như vậy, vì cấu trúc không nhất thiết phải là kiểu POD.
Steve Jessop

6
rõ ràng ... struct và class gần như tương đương nhau, nhưng trong "doanh nghiệp", chúng tôi gọi 'struct là một công cụ thu thập dữ liệu đơn giản, thường không có ctor và dtor, thường có giá trị ngữ nghĩa ...
ugasoft

2
Đối với tôi, C ++ đã sai khi tạo struct giống với từ khóa lớp hoặc gần với: struct chỉ thêm quyền truy cập mặc định công khai vào lớp. Tôi đã đơn giản hơn để tạo ra các cấu trúc giống như C và chúng tôi sẽ có POD vào ngày 0 của c ++.
user1708042

ugasoft: câu trả lời của bạn có thể sai lệch - nhận xét của bạn đã giải thích chi tiết còn thiếu mà nó được sử dụng như thế trong thực tế, thay vì tiêu chuẩn. Whoa, 8 năm, bạn thậm chí còn ở đây? ;-)
hauron

Ngoại trừ một chuỗi vì bạn không thể sao chép chuỗi đó bằng memcpy mà không xác định trước độ dài chuỗi.

12

Theo tôi hiểu, POD (PlainOldData) chỉ là dữ liệu thô - không cần:

  • được xây dựng,
  • Bị phá hủy,
  • để có các toán tử tùy chỉnh.
  • Không được có chức năng ảo,
  • và không được ghi đè toán tử.

Làm thế nào để kiểm tra nếu một cái gì đó là POD? Vâng, có một cấu trúc cho cái gọi là 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)>
  { };
}

(Từ tiêu đề type_traits)


Tài liệu tham khảo:


2
Không chính xác, loại POD có thể có các hàm thành viên hoặc toán tử quá tải. (Nhưng nó có thể không có chức năng thành viên ảo.)
Colin D Bennett

@ColinDBennett Vâng, đó là sự thật. Xin lỗi vì sự nhầm lẫn. Chỉnh sửa vào / ra khỏi anwser.
набиячлэвэли

10

Một đối tượng POD (dữ liệu cũ đơn giản) có một trong các loại dữ liệu này - một kiểu cơ bản, con trỏ, liên kết, struct, mảng hoặc lớp - không có hàm tạo. Ngược lại, một đối tượng không phải POD là một đối tượng mà hàm tạo tồn tại. Một đối tượng POD bắt đầu thời gian tồn tại của nó khi nó có được lưu trữ với kích thước phù hợp với loại của nó và thời gian tồn tại của nó kết thúc khi việc lưu trữ cho đối tượng được sử dụng lại hoặc giải phóng.

Các loại PlainOldData cũng không được có bất kỳ:

  • Các hàm ảo (là của riêng chúng hoặc được kế thừa)
  • Các lớp cơ sở ảo (trực tiếp hoặc gián tiếp).

Một định nghĩa lỏng lẻo hơn của PlainOldData bao gồm các đối tượng với các hàm tạo; nhưng loại trừ những người có bất cứ điều gì ảo. Vấn đề quan trọng với các loại PlainOldData là chúng không đa hình. Kế thừa có thể được thực hiện với các loại POD, tuy nhiên, nó chỉ nên được thực hiện cho Mã hóa triển khai (tái sử dụng mã) và không phải là đa hình / phân nhóm.

Một định nghĩa phổ biến (mặc dù không hoàn toàn chính xác) là loại PlainOldData là bất cứ thứ gì không có VeeTable.


Câu trả lời của Yuor rất hay, nhưng câu hỏi này đã chấp nhận câu trả lời 8 năm trước, cộng với một số câu trả lời hay khác. Bạn có thể đóng góp nhiều hơn cho SO nếu bạn sử dụng kiến ​​thức của mình để trả lời các câu hỏi chưa được trả lời)))
mvidelgauz 16/8/2016

10

Tại sao chúng ta cần phân biệt giữa POD và không phải POD?

C ++ bắt đầu cuộc sống như một phần mở rộng của C. Trong khi C ++ hiện đại không còn là siêu bộ nghiêm ngặt của C, mọi người vẫn mong đợi mức độ tương thích cao giữa hai loại.

Nói một cách đơn giản, một loại POD là một loại tương thích với C và có lẽ quan trọng không kém là tương thích với các tối ưu hóa ABI nhất định.

Để tương thích với C, chúng ta cần thỏa mãn hai ràng buộc.

  1. Bố cục phải giống với loại C tương ứng.
  2. Loại phải được truyền đến và trả về từ các hàm theo cùng cách với loại C tương ứng.

Một số tính năng C ++ không tương thích với điều này.

Các phương thức ảo yêu cầu trình biên dịch chèn một hoặc nhiều con trỏ vào các bảng phương thức ảo, một cái gì đó không tồn tại trong C.

Các hàm tạo sao chép do người dùng định nghĩa, các hàm tạo di chuyển, các phép gán sao chép và các hàm hủy có ý nghĩa cho việc truyền và trả về tham số. Nhiều C ABI vượt qua và trả về các tham số nhỏ trong các thanh ghi, nhưng các tham chiếu được truyền cho hàm tạo / xác định / hàm hủy do người dùng xác định chỉ có thể hoạt động với các vị trí bộ nhớ.

Vì vậy, cần phải xác định loại nào có thể được dự kiến ​​là "tương thích C" và loại nào không thể. C ++ 03 có phần quá khắt khe về vấn đề này, bất kỳ hàm tạo nào do người dùng xác định sẽ vô hiệu hóa các hàm tạo tích hợp và mọi nỗ lực để thêm chúng trở lại sẽ dẫn đến chúng là do người dùng định nghĩa và do đó loại không phải là nhóm. C ++ 11 đã mở ra mọi thứ khá nhiều, bằng cách cho phép người dùng giới thiệu lại các hàm tạo tích hợp.


8

Ví dụ về tất cả các trường hợp không phải POD với các hiệu ứng static_asserttừ C ++ 11 đến C ++ 17 và POD

std::is_pod đã được thêm vào C ++ 11, vì vậy bây giờ chúng ta hãy xem xét tiêu chuẩn đó.

std::is_podsẽ bị xóa khỏi C ++ 20 như được đề cập tại https://stackoverflow.com/a/48435532/895245 , hãy cập nhật thông tin này khi có hỗ trợ thay thế.

Các hạn chế POD đã trở nên ngày càng thoải mái hơn khi tiêu chuẩn phát triển, tôi hướng đến việc bao gồm tất cả các thư giãn trong ví dụ thông qua ifdefs.

libstdc ++ có rất ít thử nghiệm tại: https://github.com/gcc-mirror/gcc/blob/gcc-8_2_0-release/libstdc%2B%2B-v3/testsuite/20_util/is_pod/value.cc nhưng nó chỉ là quá ít Người bảo trì: vui lòng hợp nhất điều này nếu bạn đọc bài viết này. Tôi lười kiểm tra tất cả các dự án thử nghiệm C ++ được đề cập tại: /software/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
        // /programming/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.
        // /programming/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:
            // /programming/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:
    // /programming/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
        // /programming/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 ngược dòng .

Đã thử nghiệm với:

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

trên Ubuntu 18.04, GCC 8.2.0.


4

Khái niệm POD và đặc điểm loại std::is_podsẽ không được chấp nhận trong C ++ 20. Xem câu hỏi này để biết thêm thông tin.


-7

Với C ++, Plain Old Data không có nghĩa là những thứ như int, char, v.v. là những loại duy nhất được sử dụng. Plain Old Data thực sự có nghĩa là trong thực tế, bạn có thể lấy một cấu trúc ghi nhớ nó từ một vị trí trong bộ nhớ sang một vị trí khác và mọi thứ sẽ hoạt động chính xác như bạn mong đợi (nghĩa là không nổ tung). Điều này phá vỡ nếu lớp của bạn, hoặc bất kỳ lớp nào mà lớp của bạn chứa, có một thành viên là con trỏ hoặc tham chiếu hoặc lớp có chức năng ảo. Về cơ bản, nếu con trỏ phải được tham gia ở đâu đó, thì đó không phải là Dữ liệu cũ đơn giản.


6
Con trỏ được phép trong các cấu trúc POD. Tài liệu tham khảo không.
j_random_hacker

1
Passant bị mất ở đây.
icbyte
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.