quitado la etiqueta de C, ya que estaba causando cierta confusión (que no debería haber estado allí, para empezar;. Historia de los foros no contestar C como sigue bienvenida aunque :)Creación de objetos de tamaño dinámicamente
En algunas cosas que he hecho, he encontrado la necesidad de crear objetos que tengan un tamaño dinámico y un tamaño estático, donde la parte estática son los miembros de tu objeto básico, la parte dinámica es, sin embargo, una matriz/búfer anexada directamente en la clase, manteniendo la memoria contigua, disminuyendo así la cantidad de asignaciones necesarias (estos son objetos no reubicables), y disminuyendo la fragmentación (aunque como un inconveniente, puede ser más difícil encontrar un bloque de un tamaño lo suficientemente grande, sin embargo eso es mucho más raro, si incluso debería Ccur en absoluto, que fragmentación de montón. Esto también es útil en dispositivos integrados donde la memoria es escasa (sin embargo, actualmente no hago nada para dispositivos integrados), y cosas como std :: string deben evitarse, o no pueden usarse como en el caso de uniones triviales.
Generalmente el camino me gustaría ir sobre esto sería (ab) uso de malloc (std :: string no se utiliza a propósito, y por diversas razones):
struct TextCache
{
uint_32 fFlags;
uint_16 nXpos;
uint_16 nYpos;
TextCache* pNext;
char pBuffer[0];
};
TextCache* pCache = (TextCache*)malloc(sizeof(TextCache) + (sizeof(char) * nLength));
Sin embargo, esto no lo hace siento muy bien conmigo, ya que en primer lugar me gustaría hacer esto usando el ambiente nuevo, y por lo tanto en un C++, y en segundo lugar, se ve horrible: P
así que el siguiente paso era una plantilla de C++ Varient:
template <const size_t nSize> struct TextCache
{
uint_32 fFlags;
uint_16 nXpos;
uint_16 nYpos;
TextCache<nSize>* pNext;
char pBuffer[nSize];
};
Este h in embargo tiene el problema de que almacenar un puntero a un objeto de tamaño variable se hace 'imposible', por lo que entonces el siguiente trabajo en torno a:
class DynamicObject {};
template <const size_t nSize> struct TextCache : DynamicObject {...};
Sin embargo, esto aún requiere de fundición, y tener punteros a DynamicObject por todo el lugar se convierte en ambiguo cuando se más de un objeto de tamaño dinámico se deriva de él (también se ve horrible y puede sufrir de un error que obliga a las clases vacías a seguir teniendo un tamaño, aunque es probable que sea un error arcaico, extinto ...).
Luego fue la siguiente:
class DynamicObject
{
void* operator new(size_t nSize, size_t nLength)
{
return malloc(nSize + nLength);
}
};
struct TextCache : DynamicObject {...};
la que se ve mucho mejor, pero podría interferir con los objetos que ya tienen sobrecargas de nuevo (que incluso podría afectar a la colocación de nuevo ...).
Finalmente se me ocurrió con la colocación de nueva abusar:
inline TextCache* CreateTextCache(size_t nLength)
{
char* pNew = new char[sizeof(TextCache) + nLength];
return new(pNew) TextCache;
}
Sin embargo, esto es probablemente la peor idea hasta el momento, para un buen número de razones.
¿Hay alguna forma mejor de hacerlo? o ¿alguna de las versiones anteriores sería mejor, o al menos mejorable? ¿Incluso se considera una práctica de programación segura y/o mala?
como he dicho anteriormente, yo estoy tratando de evitar dobles asignaciones, porque esto no debería necesitar 2 asignaciones, y hacer que este hace que escribir (serialización) estas cosas a los archivos mucho más fácil. La única excepción al requisito de asignación doble que tengo es cuando básicamente no hay gastos generales. La única causa en la que me he encontrado es que asigné memoria de forma secuencial desde un búfer fijo (using this system, que se me ocurrió), sin embargo, también es una excepción especial para evitar la copia superflua.
¿Hay alguna razón por la que no desee utilizar STL? –
@ Kornel: tal vez por la etiqueta 'C', pero los ejemplos sugieren que tal vez la etiqueta C sea superflua (aunque mi respuesta se concentre en C). –
@Kornel: algunas de las cosas que tengo en mente no pueden usar STL, ya sea porque: a) usan asignadores que no son amigables con STL, ob) son asignadores ellos mismos, y usar STL derrotaría al todo el propósito de su existencia. – Necrolis