Por lo que vale ... también puede beneficiarse de usar otro idioma.
Sé que el patrón Flyweight
es bastante furor, pero aquí también podría beneficiarse si no asigna esos millones de objetos.
Si le parece extraño, piense en el objeto String
en Python
. Como en muchos idiomas recientes, String
son inmutables en Python
. Por supuesto, el objeto que manipulas puede cambiar, pero el verdadero String
no: tu identificador simplemente se reubica.
Por supuesto, Python
tiene recolección de basura automática que lo hace mucho más fácil, sin embargo, podría funcionar para usted también. Este es un boceto:
class FooImpl;
class Foo
{
public:
explicit Foo(int i): mImpl(FooImpl::Build(i)) {}
int foo() const { return mImpl->foo(); }
void foo(int i) { mImpl = mImpl->foo(i); }
private:
const FooImpl* mImpl;
}; // class Foo
class FooImpl
{
public:
static const FooImpl* Build(int i)
{
typedef std::unordered_set<FooImpl> foos_type;
FooImpl tmp(i);
foos_type::iterator it = gFooImplCollection.insert(tmp);
return &(*it);
}
int foo() const { return mFoo; }
const FooImpl* foo(int i) const
{
return Build(i);
}
// Useful thingy
bool operator==(const FooImpl& rhs) const { return mFoo == rhs.mFoo; }
size_t hash() const { return mFoo; }
private:
explicit FooImpl(int i): mFoo(i) {}
int mFoo;
};
std::unordered_set<FooImpl> gFooImplCollection;
Por supuesto, esto es muy áspera , sólo para darle una idea. Si la cantidad potencial de elementos diferentes es importante, necesita recolección de basura.
Recolección de basura siendo otro tema, prefiero dejarles con la idea de una clase Immutable
núcleo (sólo expone const
métodos) y un mango mutable (que simplemente cambia la clase principal al que apunta cuando se le preguntó a cambios).
Y ahora que ha tomado el tiempo para leer, Boost lo tiene: Boost.Flyweight :)
Nota:
Parece importante precisa, porque Foo
se supone que es asignado (en la pila) millones de veces, su tamaño debe permanecer lo más cerca posible de un puntero. Esto se logra usando el couting de referencia Intrusive
(espero que eso sea lo que hace Boost). Además, no es necesario tener virtual
métodos en Foo
, virtual
en FooImpl
y Build
de hecho puede llamar a AbstractFactory
detrás de las escenas.
Así, desde Foo
:
- no tiene ninguna clase base
- no tiene ningún métodos virtuales
- sólo tiene un atributo (un puntero)
Su tamaño efectivo será el tamaño del puntero ... que es el mejor que se puede esperar si no desea almacenar un identificador de un costo de búsqueda de incurrir en cada llamada :)
Tener funciones virtuales solo agrega 4 bytes más al objeto (8 para 64 bits). Derivar de la clase base no cuesta nada. (Suponen una herencia única). – kennytm
También debe considerar hacer una asignación más rápida usando un asignador personalizado. – yesraaj
Lo que debe hacer depende de lo que esté haciendo. ¿Qué estás haciendo? – GManNickG