2011-09-09 2 views
1

Правильно ли написать функцию, которая возвращает char *?Функция возвращает char *

Что-то вроде этого:

char * func() 
{ 
char *c = new char[3]; 
strcpy(c, "hi"); 
c[2] = '\0'; 
return c; 
} 

int main() 
{ 
char *c; 
c = func(); 
//code using c 
delete [] c; 
return 1; 
} 

Это работает, но это правильно?

+3

правильно, в каком смысле? –

+0

@Alecs Вы не использовали функцию 'strlen' правильно – Pradeep

+0

ли данные в памяти, выделенные в локальной функции, остаются нетронутыми, когда мы выйдем из локальной функции? – Alecs

ответ

6

Это правильно (предполагается, что вы имели в виду strcpy, а не strlen), но из документации функции должно быть очень ясно, что ответственность за освобождение возвращаемого указателя и какой метод он должен использовать для освобождения это (new =>delete, new [] =>delete[], malloc =>free, и т.д). Это «способ» сделать это.

Это зависит от пользователей вашей функции (включая вас через несколько месяцев, когда вы ее написали), чтобы прочитать документацию, чтобы все было в порядке, поэтому она довольно подвержена ошибкам; Кроме того, в C++ существует еще несколько осложнений, которые отсутствуют в C (а именно: исключения), которые делают использование исходных указателей в этих контекстах не такой хорошей идеей.

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

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

#include <string> 

std::string func() 
{ 
    return "hi"; // actually, to be more explicit it should be return std::string("hi") 
} 

int main() 
{ 
    std::string c; 
    c=func(); 
    return 1; 
} 

Вот так, не нужно беспокоиться о выделенных/deallocations и исключения, все это автоматически обрабатываются std::string класса, так что вы можете управлять почти так же, как они были построены.

+1

И освободите его с помощью 'delete []', _not_ 'free'. – paxdiablo

+0

Я думаю, что если он задает такой вопрос, он не очень обеспокоен документацией и инкапсуляциями, умными указателями и исключениями и т. Д. – quasiverse

+0

@paxdiablo: Я расширил ответ. –

2

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

Но это не действительно C++. В C++ вы должны использовать std::string.

1

Ваш код технически корректен. Тем не менее, я думаю, что большинство SO-ers здесь имеют оговорки в отношении того, считается ли это «хорошим» кодом или нет.

Для начала:

  • Выберите значимые имена переменной/функции. c и func не очень описательны и затрудняют понимание пользователями того, что вы пытаетесь сделать.
  • Обычно у вас должна быть соответствующая функция, которая очищает любые ресурсы, выделенные вашей функцией.
  • Предпочитают strncpy() над strcpy(), чтобы предотвратить неожиданные переполнения буфера (или посмотреть в класс Струнный)
+0

1) Я знаю, я решил, что для такого небольшого примера короткие имена лучше 2) в этом случае, как я могу написать функцию, которая будет очищаться? 3) в моей реальной программе я использую strncpy, поэтому я автоматически добавил символ '\ 0' вручную – Alecs

+0

К сожалению, 'strncpy' - это не подсчитанная версия' strcpy', но это функция, предназначенная для буферов фиксированного размера; он добавляет бесполезное заполнение NUL, когда копируемая строка короче, чем буфер, но NUL завершает ее, когда она длиннее. Я думаю, что лучшим стандартом, считающимся альтернативой 'strcpy', является' * target = 0; strncat (цель, источник, размер); '. –

2

Это работает, но это правильно?

Ваш код правильный.

Однако это зависит от контекста, если это хорошая практика программирования или нет. Для этой минимальной программы, которую вы опубликовали, я предпочту не использовать new[] и delete[]. Но предпочел бы полагаться на std::string.

Demo.

0

попробовать:

char * func() 
{ 
char * c = new char[3]; 
strcpy(c,"hi"); 
return c; 
} 

int main() 
{ 
char *c; 
c = func(); 
//code using c 
delete [] c; 
return 0; 
} 
Смежные вопросы