temperamento segun rasgos psicologia personalidad freud ejemplos definicion carácter caracteristicas caracter c++ c++14 metaprogramming sfinae c++20

c++ - segun - temperamento y caracter psicologia



¿Qué rasgo/concepto puede garantizar que un objeto esté bien definido? (3)

¿Qué (mínimo) rasgo / concepto puede garantizar que un objeto esté bien definido?

Según la referencia std::memset en cppreference, el comportamiento de memset en un tipo que no es memset no está definido. Así que si está bien hacer un memset entonces puede agregar static_assert a su clase para verificar si hay algo similar.

template<class T> T zero_initialize() { static_assert(std::is_trivial_v<T>, "Error: T must be TriviallyCopyable"); T result; std::memset(&result, 0, sizeof(result)); return result; }

Aquí utilizamos std::is_trivial_v para asegurarnos de que no solo la clase pueda copiarse de manera trivial, sino que también tiene un constructor predeterminado trivial, por lo que sabemos que es seguro que no se inicialice.

¿Debo usar std::uninitialized_fill lugar de std::memset ? ¿Y por qué?

No necesita hacerlo aquí, ya que solo está inicializando un solo objeto.

¿Está esta función obsoleta por una de las sintaxis de inicialización de C ++ para un subconjunto de tipos? ¿O será con el próximo de las futuras versiones de C ++?

El valor o la inicialización reforzada hacen esta función "obsoleta". T() y T{} le darán un valor inicializado T y si T no tiene un constructor predeterminado, se inicializará con cero. Eso significa que podrías reescribir la función como

template<class T> T zero_initialize() { static_assert(std::is_trivial_v<T>, "Error: T must be TriviallyCopyable"); return {}; }

Digamos que he definido una función zero_initialize() :

template<class T> T zero_initialize() { T result; std::memset(&result, 0, sizeof(result)); return result; } // usage: auto data = zero_initialize<Data>();

Llamar a zero_initialize() para algunos tipos daría lugar a un comportamiento indefinido 1, 2 . Actualmente estoy aplicando T para verificar std::is_pod . Con ese rasgo en desuso en C ++ 20 y la llegada de conceptos, tengo curiosidad por saber cómo debe evolucionar zero_initialize() .

  1. ¿Qué (mínimo) rasgo / concepto puede garantizar que un objeto esté bien definido?
  2. ¿Debo usar std::uninitialized_fill lugar de std::memset ? ¿Y por qué?
  3. ¿Está esta función obsoleta por una de las sintaxis de inicialización de C ++ para un subconjunto de tipos? ¿O será con el próximo de las futuras versiones de C ++?

1) Borrar todos los miembros de una clase .
2) ¿Cuál sería la razón para "comportamientos indefinidos" al usar memset en la clase de biblioteca (std :: string)? [cerrado]


El rasgo definible más general que garantiza que su zero_initialize realidad inicialice los objetos a cero es

template <typename T> struct can_zero_initialize : std::bool_constant<std::is_integral_v< std::remove_cv_t<std::remove_all_extents_t<T>>>> {};

No es demasiado útil. Pero la única garantía acerca de las representaciones de tipos fundamentales en modo bit o byte en el Estándar es [basic.fundamental] / 7 "Las representaciones de tipos integrales definirán los valores mediante el uso de un sistema de numeración binaria pura". No hay garantía de que un valor de punto flotante con todos los bytes cero sea un valor cero. No hay garantía de que cualquier valor de puntero o puntero a miembro con todos los bytes cero sea un valor de puntero nulo. (Aunque ambos de estos son generalmente verdaderos en la práctica).

Si todos los miembros no estáticos de un tipo de clase trivialmente copiable son tipos integrales (calificados de (cv)), creo que eso también estaría bien, pero no hay una forma posible de probar eso, a menos que la reflexión llegue a C ++.


Técnicamente, no hay ninguna propiedad de objeto en C ++ que especifique que el código de usuario puede legalmente memset un objeto C ++. Y eso incluye POD, así que si quieres ser técnico, tu código nunca fue correcto. Incluso TriviallyCopyable es una propiedad sobre la realización de copias en bytes entre objetos existentes (a veces a través de un búfer de bytes intermedio); no dice nada sobre inventar datos y meterlos en los bits del objeto.

Dicho esto, puede estar razonablemente seguro de que esto funcionará si prueba is_trivially_copyable y is_trivially_default_constructible . Lo último es importante, porque algunos tipos de TriviallyCopyable todavía quieren poder controlar sus contenidos. Por ejemplo, un tipo de este tipo podría tener una variable int privada que siempre es 5, inicializada en su constructor predeterminado. Siempre que ningún código con acceso a la variable la cambie, siempre será 5. El modelo de objetos C ++ lo garantiza.

Por lo tanto, no se puede memset un objeto de este tipo y aún así obtener un comportamiento bien definido del modelo de objetos.