2013-07-17 3 views
2
struct A 
{ 
    int i; 
}; 

struct B 
{ 
B(){} 
int i; 
} 

Привет, всеКак понять этот POD правилу

Я знаю, что «POD означает тип Plain Old Data, который по определению не может иметь определенный пользователем конструктор». Но я не могу понять, почему это правило действует, когда «определение имеет пользовательский default-con».

Нет разницы в их макете памяти. Почему тип A является POD, но не B?

+0

Добавить флаг языка. C++, не так ли? – doctorlove

+2

Возможный дубликат [Что такое типы POD в C++?] (Http://stackoverflow.com/questions/146452/what-are-pod-types-in-c) – Macmade

+0

Потому что язык говорит так? POD означает, что состояние выражается полностью членами, но наличие определяемого пользователем конструктора означает, что в логике конструктора есть дополнительное состояние. –

ответ

8

Причина проста. Как только вы определяете конструктор (любой конструктор ), язык предполагает, что для класса требуется некоторая нумерация инициализации ; что просто копировать биты в его изображении будет недостаточно для создания нового экземпляра. И одна из важных характеристик POD - это то, что они могут быть memcpy'ed.

В общем, компилятор не взгляд на содержание класса , чтобы определить, является ли это POD или нет (за исключением, чтобы увидеть, если какой-либо из членов являются PODS). Он смотрит на то, что вы определили что-то , которое может повлиять на инициализацию, присвоение или уничтожение этих членов.

+5

«Тривиально-копируемый» класс в C++ 11 может быть memcpy'd, и ему разрешено иметь предоставленные пользователем конструкторы. – interjay

+0

@interjay О «Разрешено иметь предоставленные пользователем конструкторы». Вы имеете в виду, что пользовательские конструкторы используют = default? –

+0

@LeonhartSquall: Нет, тривиально копируемый класс может иметь любой конструктор, предоставленный пользователем (с поведением по умолчанию), за исключением копий и перемещений. – interjay

3

Концепция POD has been split into trivial and standardy-layout концепции. Вы можете запросить эти свойства с помощью стандартных типов.

Класс B не является POD, потому что это не тривиально. Это не тривиально, потому что у него есть предоставленный пользователем конструктор по умолчанию. Либо пропустите это, либо используйте новый синтаксис C++ 11 =default.

#include <type_traits> 
#include <iostream> 
#include <ios> 

struct A 
{ 
    int i; 
}; 

struct B 
{ 
B(){} 
int i; 
}; 

struct C 
{ 
C() = default; 
int i; 
}; 

int main() 
{ 
    std::cout << std::boolalpha << std::is_pod<A>::value << " "; 
    std::cout << std::boolalpha << std::is_trivial<A>::value << " "; 
    std::cout << std::boolalpha << std::is_standard_layout<A>::value << "\n"; 

    std::cout << std::boolalpha << std::is_pod<B>::value << " "; 
    std::cout << std::boolalpha << std::is_trivial<B>::value << " "; 
    std::cout << std::boolalpha << std::is_standard_layout<B>::value << "\n"; 

    std::cout << std::boolalpha << std::is_pod<C>::value << " "; 
    std::cout << std::boolalpha << std::is_trivial<C>::value << " "; 
    std::cout << std::boolalpha << std::is_standard_layout<C>::value << "\n"; 
} 

Online output:

true true true 
false false true 
true true true 
1

стручки позволяют компилятору сделать некоторые оптимизации. Как правило, тип POD, если компилятору разрешено обрабатывать struct так же, как и C-компилятор.

В частности, при инициализации POD-структуру, компилятор просто нужно резервировать память соответствующего размера , не нужно беспокоиться о инициализации. Инициализация может быть запрошена явно программистом, но это никогда не происходит неявно, как это может быть в случае с определяемым пользователем конструктором.

Например, пользовательский конструктор по умолчанию может потребовать, чтобы данные инициализировались до 0. В общем случае конструктор по умолчанию мог бы иметь произвольные побочные эффекты, которые должен учитывать компилятор.

+0

Что, наглядно, заключается в различии между 'malloc'ing и' new'ing? Не инициализирует ли 'new A()' инициализация? –

+2

@JonathanWakely 'new' выполняет инициализацию (обычно, вызывая конструктор),' malloc' не делает. – ComicSansMS

+0

'new A' не выполняет инициализацию, если' A' является POD, но 'new A()' выполняет инициализацию, даже если 'A' является POD.Я хочу сказать, что ваша «аналогия для иллюстративных целей» на самом деле не очень иллюстративна, потому что я могу «выделить память для массива структур POD» и до сих пор инициализировать ее компилятором. Существуют лучшие способы определения POD, чем некорректная аналогия. –