2010-02-25 6 views
4

Vous vous demandez simplement si ce type de code est recommandé pour augmenter les performances?Réutilisation de la mémoire en C++

void functionCalledLotsofTimes() { 
    static int *localarray = NULL; 

    //size is a large constant > 10 000 
    if (localarray == NULL) localarray = new int[size]; 

    //Algorithm goes here 
} 

Je suis également curieux de savoir comment les variables statiques sont implémentées par les compilateurs C++ modernes comme g ++. Sont-ils manipulés comme des variables globales?

+0

Si vous en faites un paramètre, je dirais que c'est une optimisation parfaitement valide. – GManNickG

+1

Si 'size' est constant, il y a peu de raison d'utiliser' new [] 'ici, soit de le déclarer sur la pile, soit de le passer dans la fonction comme d'autres l'ont suggéré. – Justicle

+0

@Justicle: Parfois, l'espace de pile peut être un problème. Cela dit, j'aurais dû mentionner 'std :: vector' est plus approprié qu'un pointeur brut. – GManNickG

Répondre

12

Il est déconseillé d'introduire l'état global dans une fonction. Lorsque vous avez un état global dans une fonction, vous avez des effets secondaires. Les effets secondaires provoquent des problèmes, en particulier dans les programmes multi-thread.

Voir Referential Transparency pour plus d'informations. Avec la même entrée, vous voulez toujours avoir la même sortie, quel que soit le nombre de threads que vous utilisez.

Si vous souhaitez activer plus d'efficacité, autorisez l'utilisateur à spécifier le tampon comme l'un des paramètres.

Voir la différence entre global and static variables here.

0

Il y a une grande augmentation des performances, mais vous devez faire très attention à la façon dont les données seront utilisées. Si un multi-thread vous devez fournir un contrôle d'accès aux données.
faire ce test:

 
#include <windows.h> 
#include <stdio.h> 

void StartTime (LARGE_INTEGER * pTime) 
{ 
    QueryPerformanceCounter (pTime); 
} 

ULONG EndTime(LARGE_INTEGER * pTime) 
{ 
    LARGE_INTEGER liDiff; 
    LARGE_INTEGER liFreq; 

    QueryPerformanceCounter(&liDiff); 

    liDiff.QuadPart -= pTime->QuadPart; 
    liDiff.QuadPart *= 1000; // Adjust to milliseconds, shouldn't overflow... 

    (void)QueryPerformanceFrequency(&liFreq); 

    return ((ULONG)(liDiff.QuadPart/liFreq.QuadPart)); 
} 

void functionCalledLotsofTimesStatic(int size) 
{ 
    static int *localarray = NULL; 

    //size is a large constant > 10 000 
    if (localarray == NULL) localarray = new int[size]; 

    //Algorithm goes here 

} 

void functionCalledLotsofTimesDynamic(int size) 
{ 
    int *localarray = NULL; 

    //size is a large constant > 10 000 
    if (localarray == NULL) localarray = new int[size]; 

    //Algorithm goes here 

    delete [] localarray; 
} 


int _tmain(int argc, _TCHAR* argv[]) 
{ 
    LARGE_INTEGER liTimeDynamic, liTimeStatic; 

    StartTime (& liTimeDynamic); 
    for (int loop = 0; loop < 100000 ; loop++) 
    { 
     functionCalledLotsofTimesDynamic (10000); 
    } 
    printf ("Time dynamic alocation : %lu milliseconds\n", EndTime(&liTimeDynamic)); 

    StartTime (& liTimeStatic); 
    for (int loop = 0; loop < 100000 ; loop++) 
    { 
     functionCalledLotsofTimesStatic (10000); 
    } 
    printf ("Time staic alocation : %lu milliseconds\n", EndTime(&liTimeStatic)); 

    return 0; 
} 

0

Si je ne me trompe pas, le test pour voir si la variable statique a déjà été initialisé est fait par « système » de toute façon. Pas besoin de le faire vous-même. Il suffit d'écrire

static int *localarray = new int[size]; 

Seule la première fois que la fonction est appelée, le tableau est créé.

0

Habituellement, ce type de code est caché derrière une classe d'allocateurs personnalisée qui a un grand tampon pré-alloué, de sorte que les "allocations dynamiques" ne le sont pas réellement.

De nombreuses implémentations de std :: vector ont une forme plus basique de mise en oeuvre: par défaut, elle alloue des "blocs" de mémoire en deux puissances, de sorte qu'aucune nouvelle allocation réelle ne doit être faite avant que le vecteur cultivé au double de la taille.