Как вернуть локальный массив в C ++? - PullRequest
22 голосов
/ 14 октября 2011
char *recvmsg(){
    char buffer[1024];
    return buffer;
}

int main(){
    char *reply = recvmsg();
    .....
}

Я получаю предупреждение:

предупреждение C4172: возврат адреса локальной или временной переменной

Ответы [ 12 ]

27 голосов
/ 14 октября 2011

Я бы предложил std::vector<char>:

std::vector<char> recvmsg()
{
    std::vector<char> buffer(1024);
    //..
    return buffer;
}
int main()
{
    std::vector<char> reply = recvmsg();
}

И затем, если вам когда-нибудь понадобится char* в вашем коде, вы можете использовать &reply[0] в любое время.Например,

void f(const char* data, size_t size) {}

f(&reply[0], reply.size());

И все готово.Это означает, что если вы используете C API, вы все равно можете использовать std::vector, поскольку вы можете передать &reply[0] в C API (как показано выше) и reply в C ++ API.

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

13 голосов
/ 14 октября 2011

Вам необходимо динамически выделить массив символов:

char *recvmsg(){
   char* buffer = new char[1024];
   return buffer;
}

для C ++ и

char *recvmsg(){
   char* buffer = malloc(1024);
   return buffer;
}

для C.

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

10 голосов
/ 14 октября 2011

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

Вы можете сделать это, используя динамическое выделение памяти:

char *recvmsg(){
    char *buffer = (char*)malloc(1024);
    return buffer;
}

Загвоздка в том, что вам нужно убедиться, что вы free() указатель позже, чтобы избежать утечки памяти.

Кроме того, вы можете передать буфер в функцию.

void recvmsg(char *buffer,int buffer_size){
    //  write to buffer
}

void main(){
    char buffer[1024];
    recvmsg(buffer,1024);
}

Это позволяет избежать необходимости выделения памяти. Это на самом деле предпочтительный способ сделать это.

6 голосов
/ 14 октября 2011

Проблема в том, что buffer живет в стеке и выходит из области видимости, когда вы выходите recvmsg.

Вы можете выделить buffer в куче:

char *recvmsg(){
  char *buffer = malloc(1024);
  return buffer;
}

Обратите внимание, что теперь вызывающая сторона отвечает за использование выделенной памяти:

void main(){
  char *reply = recvmsg();
  free(reply);
}
1 голос
/ 17 февраля 2015

Просто для завершения картины:

Нет необходимости выделять память с помощью malloc.Вы также можете создать буфер в стеке, но вы должны создать его в кадре стека, который живет до тех пор, пока живет потребитель буфера.Это была ошибка OP - когда вызываемый был закончен, буфер был удален, и вызывающий получил неверный указатель.

Итак, вы можете сделать следующее:

1 голос
/ 21 августа 2013
char *recvmsg(){
    char *buffer = new char;
    cout<<"\nENTER NAME : ";
    cin>> buffer;
    return buffer;
}

int main(){
    char *reply = recvmsg();
    cout<<reply;
}
1 голос
/ 14 октября 2011

Вы можете динамически создать буфер, но тогда вызывающий должен знать, чтобы освободить его.

Я думаю, что лучше передать в буфер (при условии, что recvmsg также заполняет его)

void recvmsg(char *buffer, size_t size){

}

void main(){
    char buffer[1024];
    recvmsg(buffer, sizeof(buffer));
}

Даже если вызывающий объект решит, что динамический файл лучше, он будет знать, что ему нужно освободить его, и конкретный способ сделать это (free (), delete, delete [] или, возможно, что-то особенное из пользовательского распределителя)

0 голосов
/ 16 февраля 2015

как насчет проезда по реф

char buf[1024];
PutStuffInBuff(&buf);
0 голосов
/ 14 октября 2011

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

0 голосов
/ 14 октября 2011

У вас есть несколько опций ... То, как вы это делаете сейчас, приведет к неопределенному поведению, так как массив выйдет из области видимости, как только функция hte вернется.Так что одним из вариантов является динамическое выделение памяти.

char * recmsg()
{ 
   char * array = new char[128];
   return array;
}

Просто не забудьте очистить ее с помощью метода удаления (или бесплатно, если вы использовали malloc).Во-вторых, вы можете использовать параметр ...

void recmsg(char * message, int size)
{
   if (message == 0)
      message = new char[size];
}

Опять-таки, здесь происходит то же самое, что и в предыдущем.Также обратите внимание на проверку на 0, чтобы убедиться, что вы не вызываете new для уже выделенного указателя.

Наконец, вы можете использовать вектор ..

std::vector<char> recmsg()
{
   std::vector<char> temp;

   //do stuff with vector here

   return temp;
}
...