Повторное использование памяти в C ++ - PullRequest
4 голосов
/ 25 февраля 2010

Просто интересно, такой код рекомендуется для увеличения производительности?

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

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

   //Algorithm goes here
}

Мне также любопытно, как статические переменные реализуются современными компиляторами c ++, такими как g ++. Они обрабатываются как глобальные переменные?

Ответы [ 4 ]

12 голосов
/ 25 февраля 2010

Это не рекомендуется, потому что вы вводите глобальное состояние в функцию.Когда у вас есть глобальное состояние в функции, у вас есть побочные эффекты.Побочные эффекты вызывают проблемы, особенно в многопоточных программах.

См. Ссылочная прозрачность для получения дополнительной информации.С одним и тем же вводом вы всегда хотите иметь один и тот же вывод, независимо от того, сколько потоков вы используете.

Если вы хотите повысить эффективность, разрешите пользователю самим указать буфер в качестве одного из параметров.

См. Разницу между глобальными и статическими переменными здесь .

0 голосов
/ 25 февраля 2010

Обычно такого рода код скрыт за пользовательским классом-распределителем, который имеет большой предварительно выделенный буфер, поэтому «динамические выделения» на самом деле не таковы.

Многие реализации std :: vector имеют более базовую форму реализации этого: по умолчанию он распределяет «блоки» памяти в степени двух, так что никаких реальных новых выделений не нужно делать до тех пор, пока вектор не вырос в два раза больше.

0 голосов
/ 25 февраля 2010

Если я не ошибаюсь, проверка того, была ли статическая переменная уже инициализирована, в любом случае выполняется "системой" Не нужно делать это самостоятельно. Просто напишите

static int *localarray = new int[size];

Массив будет создан только при первом вызове функции.

0 голосов
/ 25 февраля 2010

Производительность значительно выросла, но вы должны быть очень осторожны с тем, как будут использоваться данные. Если многопоточность, вы должны обеспечить контроль доступа к данным.
сделать этот тест:

#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;
}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...