Могу ли я использовать статическую переменную для «кэширования» результата? C ++ - PullRequest
2 голосов
/ 26 мая 2010

Я использую функцию, которая возвращает символ *, и сейчас я получаю предупреждение компилятора «возвращение адреса локальной или временной переменной», поэтому я предполагаю, что мне придется использовать статическую переменную для возврата, мой вопрос можно сделать что-то вроде, если (переменная уже установлена) вернуть var, иначе сделать функцию и вернуть var?

Это моя функция:

char * GetUID()
{
   TCHAR buf[20];

   StringCchPrintf(buf, 20*sizeof(char), TEXT("%s"), 
            someFunction());

   return buf;
}

И вот что я хочу сделать:

char * GetUID()
{
   static TCHAR buf[20];

   if(strlen(buf)!=0) return buf;

   StringCchPrintf(buf, 20*sizeof(char), TEXT("%s"), 
            someFunction());

   return buf;
}

Хорошо ли использовать статические переменные? И я должен использовать ZeroMemory (& buf, 20 * sizeof (char)) ? Я удалил его, потому что, если я использую его выше if (strlen ...), моя длина TCHAR никогда не равна 0, я должен использовать это ниже?

Ответы [ 5 ]

4 голосов
/ 26 мая 2010

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

Обычно шаблон в C / C ++ состоит в том, чтобы выделить блок памяти и передать указатель на этот блок в вашу функцию. например,

void GetUID( char* buf )
{
    if(strlen(buf)!=0) return;

    StringCchPrintf(buf, 20*sizeof(char), TEXT("%s"), someFunction());
}

Если вы хотите, чтобы сама функция (GetUID) обрабатывала кеширование результата, вы можете использовать статическое, одноэлементное (OOP) или локальное хранилище потока . (например, в Visual C ++)

__declspec(thread) TCHAR buf[20];
3 голосов
/ 26 мая 2010

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

2 голосов
/ 26 мая 2010

Вместо этого вы должны динамически выделить buf, используя new, а затем вернуть его. Но имейте в виду, что вызывающая сторона будет ответственна за освобождение памяти.

Еще лучше, используйте std::string вместо char *.

1 голос
/ 26 мая 2010

Вы можете сделать это, но это не будет потокобезопасным. Вы также должны быть осторожны с тем, что вы делаете с результатом, так как вы не можете сохранить его между последующими вызовами функции (конечно, без копирования).

Вы должны также инициализировать статическую переменную пустой строкой.

0 голосов
/ 26 мая 2010

Вот как бы я это сделал. Кеширует; он не полагается на то, что буфер равен 0.

У него есть неявное предположение, что «buf» будет одинаковым от потока к потоку, что не (насколько мне известно) правильно. Я бы использовал глобальный для этой цели.

//returns a newly allocated buffer, every time. remember to delete [] it.
char * GetUID()
{
   static TCHAR buf[20];
   static bool run = false;
   TCHAR ret_mem = new TCHAR[20];

   if(run) 
  { return ret_mem; }

  //do stuff to the buf
  //assuming - dst, src, size. 
  memcpy(ret_mem, buf, 20);

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