Управление памятью с функцией возврата * - PullRequest
1 голос
/ 26 декабря 2010

Сегодня, не задумываясь, я написал простую функцию возврата к символу *, основанную на операторе switch заданных значений перечисления.Это, однако, заставило меня задуматься, как я мог освободить эту память.То, что я сделал, было примерно так:

char* func()
{
    char* retval = new char[20];
    // Switch blah blah - will always return some value other than NULL since default:
    return retval;
}

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

void func(char*& in)
{
    // blah blah switch make it do something
}

int main()
{
    char* val = new char[20];

    func(val);
    // Do whatever with func (normally func within a data structure with specific enum set so could run multiple times to change output)

    delete [] val;
    val = NULL;
    return 0;
}

Кто-нибудь еще мог бы понять это и / или объяснение, что использовать?Деннис М.

Ответы [ 4 ]

2 голосов
/ 26 декабря 2010

Если вы планируете возвращать необработанные указатели из функции, вы должны четко указать в документации, на которой лежит ответственность за удаление указателя, т. Е. Кто владеет им. В этом случае вы должны явно указать, что владение указателем передается вызывающей стороне, которая отвечает за delete it.

Хотя многие в порядке, просто указав владельца в документации, часто лучше применять эту политику в коде. В частности, для этого часто используются умные указатели : текущий стандарт C ++ предоставляет умный указатель std::auto_ptr, который передает право собственности на копию, т.е. когда вы возвращаете его вызывающей стороне, вы передаете право собственности на цель std::auto_ptr. Обратите внимание, что std::auto_ptr автоматически delete указывает на уничтожение памяти, если она все еще владеет ею. Предстоящий стандарт C ++ предоставляет std::unique_ptr, который работает аналогичным образом, но с использованием семантики перемещения.

К сожалению, std::auto_ptr не предназначен для массивов (которым нужно delete [] вместо delete), поэтому вы не можете использовать его для своих целей. Я думаю, что решение не включать auto_ptr для массивов было принято намеренно, поскольку STL уже предоставляет все контейнеры, которые могут вам понадобиться, если вам нужно вернуть коллекцию элементов, которые обрабатывают свои собственные средства управления памятью и копируют.

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

2 голосов
/ 26 декабря 2010

Рассматривали ли вы использование типа STL или другого класса вместо возврата необработанного указателя? Например, если ваш char * является строкой, используйте вместо него std::string и избегайте риска утечки:

std::string func()
{
    std::string retval("");

    // Switch blah blah - will always return some value other than NULL since default:

    return retval;
}
2 голосов
/ 26 декабря 2010

Вы можете написать такие функции в паре, как

Xyz* CreateXyz();
void DestroyXyz(Xyz *xyz);


Abc* NewAbc();
void DeleteAbc(Abc *abc);

Или вы можете просто передать ответственность за удаление Xyz / Abc клиентам, то есть те, кто вызывает функцию, должны также сделать delete для возвращенного объекта после его использования.

Что бы вы ни выбрали, укажите в своей документации как созданный объект должен быть уничтожен.

Я бы предпочел парные функции, особенно если есть много вещей, которые нужно рассмотреть перед удалением!

Кстати, вы предпочитаете использовать std::string вместо char*. Используйте как можно больше STL. Они могут решить большинство ваших проблем! Приведенный выше совет предназначен для ситуаций, когда STL не подходит! В общем, предпочитаю STL!

0 голосов
/ 26 декабря 2010

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

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