Pregunta

Tengo una clase con el método estático que tiene una variable estática local. Quiero esa variable que se calcula / evalúa una vez (la primera vez que llame a la función) y para cualquier invocación posterior, no se evalúa más. ¿Como hacer eso? Aquí está mi clase:

template<
    typename T1 = int, unsigned N1 = 1,
    typename T2 = int, unsigned N2 = 0,
    typename T3 = int, unsigned N3 = 0,
    typename T4 = int, unsigned N4 = 0,
    typename T5 = int, unsigned N5 = 0,
    typename T6 = int, unsigned N6 = 0,
    typename T7 = int, unsigned N7 = 0,
    typename T8 = int, unsigned N8 = 0,
    typename T9 = int, unsigned N9 = 0,
    typename T10 = int, unsigned N10 = 0,
    typename T11 = int, unsigned N11 = 0,
    typename T12 = int, unsigned N12 = 0,
    typename T13 = int, unsigned N13 = 0,
    typename T14 = int, unsigned N14 = 0,
    typename T15 = int, unsigned N15 = 0,
    typename T16 = int, unsigned N16 = 0>
struct GroupAlloc
{
    static const uint32_t sizeClass;
    static uint32_t getSize()
    {
        static uint32_t totalSize = 0;

        totalSize += sizeof(T1)*N1;
        totalSize += sizeof(T2)*N2;
        totalSize += sizeof(T3)*N3;
        totalSize += sizeof(T4)*N4;

        totalSize += sizeof(T5)*N5;
        totalSize += sizeof(T6)*N6;
        totalSize += sizeof(T7)*N7;
        totalSize += sizeof(T8)*N8;

        totalSize += sizeof(T9)*N9;
        totalSize += sizeof(T10)*N10;
        totalSize += sizeof(T11)*N11;
        totalSize += sizeof(T12)*N12;

        totalSize += sizeof(T13)*N13;
        totalSize += sizeof(T14)*N14;
        totalSize += sizeof(T15)*N15;
        totalSize += sizeof(T16)*N16;

        totalSize = 8*((totalSize + 7)/8);

        return totalSize;
    }
};

EDIT:

Gracias a todos por su ayuda rápida. 1 para todos. Elegí la respuesta de Tyler McHenry, ya que no necesita ninguna comparación, evaluación de la función puramente estática. Voy a necesitar este código para evitar otro asignador de modo "si" debería ser mejor. Gracias de nuevo!

EDIT:

La respuesta de gf resultó ser la mejor opción, ya que se ocupa de la asignación durante el tiempo de compilación y guarda el programa de dolor de cabeza flujos seguros e inicialización explícita. Sin embargo, yo respeto la mejor respuesta anterior. Voy a dar crédito aquí en lugar de cambiar la marca de la señal. Gracias a todos por ayudar!

¿Fue útil?

Solución

Hacer otra función estática que hace el cálculo, y el uso que para la inicialización de la variable, por ejemplo.

static uint32_t computeSize() 
{
  uint32_t init_totalSize;

  // Lots of code

  return init_totalSize;
}

static uint32_t getSize()
{
  static uint32_t totalSize = computeSize();
  return totalSize;
}

Las variables estáticas están garantizados para ser inicializado exactamente una vez (la primera vez que se utiliza la función de las contienen).

Editar Pero esto es no seguro para subprocesos. Esta página explica por qué en gran detalle .

Para que sea más seguro para subprocesos, no es suficiente para envolver la inicialización de totalSize (la llamada a computeSize) en una sección crítica, debido a la inicialización variable estática es "magia compilador", y puede ser que la variable que se somete inicialización en cualquier momento durante la llamada a getSize antes de su uso, incluso antes de la primera declaración de la función. Lo que hay que hacer es evitar que más de un hilo de getSize incluso llamando al mismo tiempo, lo que se puede lograr con otro nivel de indirección, por ejemplo.

static uint32_t computeSize() 
{
  uint32_t init_totalSize;

  // Lots of code

  return init_totalSize;
}

static uint32_t real_getSize()
{
  static uint32_t totalSize = computeSize();
  return totalSize;
}

static uint32_t getSize()
{
  uint32_t totalSize;
  /* --- Enter Critical Section (acquire lock) -- */
  totalSize = real_getSize();
  /* --- Exit Critical Section (release lock) -- */
  return totalSize;
}

Esto evita que dos hilos de incluso entrar en la función que contiene la variable estática al mismo tiempo, y asegúrese de que su inicialización ocurrirá dentro de una sección crítica.

Otros consejos

Mover el cálculo en una función auxiliar:

static uint32_t totalSize = calculateTotalSize();

La función de ayuda sólo será invocado cuando se inicializa totalSize.

Un poco tarde, pero ¿por qué haces un (potencialmente) cálculo de tiempo de ejecución aquí en absoluto? Use constantes en tiempo de compilación y que ni siquiera puede tener cualquier problema de roscado:

template<
  typename T1, unsigned N1,
  typename T2, unsigned N2,
  /* ... */
>
struct totalSize {
    static const uint32_t sum = 
        sizeof(T1)*N1
      + sizeof(T2)*N2
      /* ... */
      ;
    static const uint32_t value =
        8*((sum + 7)/8);
};

uint32_t GroupAlloc::getSize() {
    return totalSize<T1,N1,T2,N2,/*...*/>::value;
}

Algo así como:

static uint32_t getSize()
{
    static uint32_t totalSize = 0;
    static bool computed = 0;
    if(computed)
      return totalSize;
    computed = 1;
    // ... go on with your computation

haría el truco. Tenga en cuenta que no es seguro para subprocesos.

static uint32_t totalSize = 0;    // initialisation performed once only
if ( totalSize == 0 ) {
        totalSize += sizeof(T1)*N1;
        totalSize += sizeof(T2)*N2;
        totalSize += sizeof(T3)*N3;
        totalSize += sizeof(T4)*N4;
        // etc
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top