c++ official




Quais são os tipos de POD em C++? (6)

Eu me deparei com esse termo tipo POD algumas vezes. O que isso significa?


Por que precisamos diferenciar entre PODs e não PODs?

C ++ começou sua vida como uma extensão de C. Embora o C ++ moderno não seja mais um superconjunto estrito de C, as pessoas ainda esperam um alto nível de compatibilidade entre os dois.

Grosso modo, um tipo POD é um tipo compatível com C e talvez igualmente importante é compatível com certas otimizações ABI.

Para ser compatível com C, precisamos satisfazer duas restrições.

  1. O layout deve ser o mesmo que o tipo C correspondente.
  2. O tipo deve ser passado e retornado de funções da mesma maneira que o tipo C correspondente.

Certos recursos do C ++ são incompatíveis com isso.

Métodos virtuais exigem que o compilador insira um ou mais ponteiros em tabelas de métodos virtuais, algo que não existe em C.

Construtores de cópia definidos pelo usuário, construtores de movimento, atribuições de cópia e destrutores têm implicações para passagem e retorno de parâmetros. Muitas ABIs passam e retornam pequenos parâmetros nos registradores, mas as referências passadas ao construtor / atribuição / destrutor definido pelo usuário só podem funcionar com localizações de memória.

Portanto, é necessário definir quais tipos podem ser "compatíveis com C" e quais tipos não podem. C ++ 03 foi um pouco estrito quanto a isso. C ++ 11 abriu as coisas um pouco.


Muito informalmente:

Um POD é um tipo (incluindo classes) onde o compilador C ++ garante que não haverá "mágica" acontecendo na estrutura: por exemplo, ponteiros ocultos para vtables, deslocamentos que são aplicados ao endereço quando ele é convertido em outros tipos ( pelo menos se o POD do alvo também), construtores ou destruidores. Grosso modo, um tipo é um POD quando as únicas coisas nele são tipos internos e combinações deles. O resultado é algo que "age como" um tipo C.

Menos informalmente:

  • int , char , wchar_t , bool , float , double são PODs, assim como versões long/short e signed/unsigned deles.
  • ponteiros (incluindo ponteiro para função e ponteiro para membro) são PODs,
  • enums são PODs
  • um const ou volatile POD é um POD.
  • Uma class , struct ou union de PODs é um POD desde que todos os membros de dados não estáticos sejam public e não possuam nenhuma classe base e nenhum construtor, destrutor ou método virtual. Membros estáticos não impedem que algo seja um POD sob esta regra. Esta regra mudou em C ++ 11 e certos membros privados são permitidos: Uma classe com todos os membros privados pode ser uma classe POD?
  • A Wikipedia está errada ao dizer que um POD não pode ter membros do tipo ponteiro para membro. Ou melhor, é correto para o texto do C ++ 98, mas o TC1 tornou explícito que os ponteiros para membros são POD.

Formalmente (C ++ 03 Standard):

3.9 (10): "Tipos aritméticos (3.9.1), tipos de enumeração, tipos de ponteiro e ponteiro para tipos de membros (3.9.2) e versões qualificadas para cv desses tipos (3.9.3) são coletivamente tipos escalares de chamadas. tipos, tipos de estruturas POD, tipos de união POD (cláusula 9), matrizes de tais tipos e versões qualificadas cv desses tipos (3.9.3) são chamados coletivamente tipos POD "

9 (4): "Uma POD-struct é uma classe agregada que não possui membros de dados não-estáticos do tipo non-POD-struct, não-POD-union (ou array de tais tipos) ou referência, e não possui define operador de cópia e nenhum destruidor definido pelo usuário Da mesma forma, um POD-union é uma união agregada que não possui membros de dados não-estáticos do tipo non-POD-struct, non-POD-union (ou array de tais tipos) ou referência e não possui um operador de cópia definido pelo usuário nem um destruidor definido pelo usuário.

8.5.1 (1): "Um agregado é uma matriz ou classe (cláusula 9) sem construtores declarados pelo usuário (12.1), nenhum membro de dados não estático protegido ou privado (cláusula 11), nenhuma classe base (cláusula 10) e sem funções virtuais (10.3). "


O conceito de POD e o tipo de caractere std::is_pod serão descontinuados em C ++ 20. Veja this questão para mais informações.


Pelo que entendi POD (PlainOldData) é apenas um dado bruto - não precisa de:

  • para ser construído,
  • ser destruído
  • ter operadores personalizados.
  • Não deve ter funções virtuais,
  • e não deve substituir os operadores.

Como verificar se algo é um POD? Bem, existe uma estrutura para isso chamada 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)>
  { };
}

(Do cabeçalho type_traits)


Referência:


Dados antigos simples

Em suma, são todos os tipos de dados internos (por exemplo, int , char , float , long , unsigned char , double , etc.) e toda a agregação de dados POD. Sim, é uma definição recursiva. ;)

Para ser mais claro, um POD é o que chamamos de "uma estrutura": uma unidade ou um grupo de unidades que apenas armazenam dados.


POD significa Plain Old Data - isto é, uma classe (seja definida com a palavra-chave struct ou a class palavras-chave) sem funções de construtores, destrutores e membros virtuais. O artigo da Wikipedia sobre o POD vai mais detalhadamente e define como:

Uma Estrutura de Dados Antigos em C ++ é uma classe agregada que contém somente PODS como membros, não possui nenhum destrutor definido pelo usuário, nenhum operador de atribuição de cópia definido pelo usuário e nenhum membro não estático do tipo ponteiro para membro.

Maiores detalhes podem ser encontrados nesta resposta para C ++ 98/03 . O C ++ 11 mudou as regras que cercam o POD, relaxando-as muito, necessitando assim de uma resposta de acompanhamento aqui .







c++-faq