Una estructura de datos simple ( eng. Plain Old Data , POD ) es un tipo de datos en lenguajes de programación modernos de alto nivel que tiene una disposición rígidamente definida de campos en la memoria que no requiere restricciones de acceso y control automático . Las variables de este tipo se pueden copiar con rutinas simples de copia de memoria como . Lo contrario es una estructura de datos administrados . memcpy
La forma más fácil de definir una estructura de datos simple es por contradicción. Si el compilador reorganiza en secreto los campos del usuario, o al crear una estructura de datos, llama en secreto al constructor , o llama al destructor cuando se destruye la estructura , o al copiar, un procedimiento de copia especial, entonces esto es administrado (es decir , no simple) estructura.
Las estructuras de datos simples tienen dos características.
El compilador puede reconstruir automáticamente la estructura de datos a su discreción (por ejemplo, cambiar el orden de los campos). En el lenguaje C++, esto solo es posible si hay una etiqueta de acceso público/privado/protegido entre los campos. Una secuencia de campos no separados por tal etiqueta deben ser colocados en la memoria en orden de declaración de campo). Tal reestructuración puede ahorrar memoria seriamente, pero rompe la compatibilidad. En los POD, esta optimización está deshabilitada.
En otras palabras: los tipos marcados como POD se organizan en la memoria exactamente como los describió el programador (quizás con alguna alineación ). Por lo tanto, solo se pueden usar POD para comunicarse entre dos bibliotecas de tiempo de ejecución . En particular, para transferir datos de un programa a otro, de un complemento a otro, para comunicarse con código escrito en otro lenguaje de programación . Para escribir rápidamente un encabezado de archivo complejo como BMP en el disco , puede formarlo en la memoria y luego escribirlo con un comando, pero la estructura de datos en la que formamos el encabezado también debe ser un POD.
Esto significa que cuando aparece un objeto, no es necesario llamar al constructor, al copiar, a la operación de asignación, y al destruir, al destructor. Esto, a su vez, proporciona los siguientes beneficios:
En C++ , POD se define por contradicción. Un tipo de datos es un POD si:
De acuerdo con el estándar C++, un tipo de datos simple se estructura exactamente como se describe (y es totalmente compatible byte a byte en el diseño de memoria con una estructura C). El compilador puede reorganizar la estructura administrada de la forma que considere más eficiente.
Definición de POD anterior a C++ 11:
Un agregado es una matriz o una clase que no tiene:
Un agregado se puede inicializar (como en C) con una lista de la forma = {1, 2, 3};
El escalar se llama:
(es decir, un tipo que no es una clase, matriz o referencia)
Un POD es un escalar , o una matriz de otros POD, o una clase que es un agregado, y además:
"Dispositivo predecible en la memoria" y "sin código de control" son propiedades de tipo similares pero diferentes. Por ejemplo, la estructura de datos STRRET[ 2] , que en Windows se usa para pasar cadenas de un administrador de memoria a otro, puede " envolverse " en el código de control, pero la segunda propiedad, el dispositivo predecible, permanece. Por lo tanto, el concepto de PODs en C++11 se divide en tres.
Una clase se llama "tener un constructor de copia trivial" si todo lo siguiente es cierto:
El constructor de copia trivial generado automáticamente es memmove().
Los términos "tener un constructor/operador de asignación/constructor de movimiento/operador de movimiento predeterminado trivial" se definen exactamente de la misma manera.
Se dice que una clase "tiene un destructor trivial" si todo lo siguiente es cierto:
Dicha clase no requiere destrucción, y la memoria que la contiene se puede desasignar sin limpiarla.
Se dice que una clase es "trivialmente copiable" si todas las funciones miembro especiales anteriores son triviales (excepto el constructor predeterminado, que puede no ser trivial). Los escalares, así como las matrices de objetos copiables trivialmente, también son copiables trivialmente. Dichos tipos se pueden copiar a través de memcpy.
Una clase se llama "trivial" si se puede copiar de forma trivial y también tiene un constructor predeterminado trivial.
En otras palabras, una clase es trivial si tiene trivial:
Una clase es un tipo de dispositivo estándar si:
Aclaremos la última condición: en el lenguaje no puede haber dos objetos diferentes del mismo tipo con la misma dirección, lo que significa que el tamaño de una clase vacía (sin campos no estáticos) no puede ser 0 (al menos 1). Sin embargo, se hace una excepción para la "parte B en la clase D: B" y su tamaño (si está vacío) puede ser estrictamente cero, lo que da como resultado que no haya "relleno" entre el comienzo de D y su primer campo. Pero al mismo tiempo, si el tipo del primer campo también es B, la excepción no se puede aplicar, porque (B *) & d y & (d. campo1) apuntan a objetos diferentes del mismo tipo, y por lo tanto el " se necesita relleno". La última condición de la lista anterior significa nada más que "en las clases de un dispositivo estándar, dicha junta está prohibida".
Dichos tipos tienen un dispositivo predecible en la memoria (por ejemplo, la dirección de un objeto como un todo es la misma que la dirección de su primer campo, naturalmente, después de reinterpret_cast al mismo tipo, por ejemplo, para anular *), pueden ser pasado a otra biblioteca en tiempo de ejecución y a otros lenguajes de programación.
Entonces POD es una matriz de otros POD, o un escalar, o una clase trivial con un dispositivo estándar, cuyos campos no estáticos también son POD.
Para trabajar con constantes de tiempo de compilación e inicialización estática, C++ 11 tiene un concepto más suave: un tipo literal . A saber:
Desde C++03, existe una diferencia entre T t; y T t();, así como entre la nueva T y la nueva T().
La versión con paréntesis vacíos se llama "inicialización de valor", y sin ellos se llama "inicialización predeterminada".
Inicialización predeterminada: si el constructor predeterminado es trivial, entonces no se hace nada, la basura permanece en el objeto. Si el constructor predeterminado no es trivial, entonces se ejecuta.
Inicialización por valor: si hay un constructor predeterminado escrito explícitamente, entonces se ejecuta. De lo contrario (es decir, si el constructor predeterminado es trivial o se genera automáticamente), primero se anula el objeto y solo entonces se ejecuta el constructor (si no es trivial). Los tipos escalares se establecen en cero cuando se inicializan con un valor.
Todos los tipos se consideran estructuras de datos simples excepto: