Макросы C ++ для обеспечения освобождения используемой памяти? - PullRequest
5 голосов
/ 06 мая 2011

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

#define withObject(ptr, value, BODY)                       \
{                                                           \
     ptr = value;                                           \
     BODY                                                   \
     delete ptr;                                            \ 
     ptr=NULL                                               \
}

Может ли этот макрос вызвать некоторые проблемы или вести себя неожиданным образом?

Редактировать: упс Iостановился на свободе.Спасибо всем за ответы.

Ответы [ 9 ]

14 голосов
/ 06 мая 2011

Нет, не делай этого. Это не предотвратит ни утечки памяти, ни случайные указатели. Вместо этого читайте на умных указателях. Текущий стандарт предоставляет один в форме auto_ptr , но доступно гораздо больше (и лучше) в зависимости от вашей платформы C ++.

Кроме того, я подозреваю, что вы можете чрезмерно использовать new и delete - они должны использоваться очень редко в вашем коде. Вы должны предпочесть использовать значения. Поэтому вместо чего-то вроде этого:

string * s = new string ( "foobar" );
....
delete s;

Вы должны просто написать:

string s( "foobar" );

и пусть компилятор управляет временем жизни строки для вас.

8 голосов
/ 06 мая 2011

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

Очень полезная библиотека Boost имеет умный указатель функциональность.

4 голосов
/ 06 мая 2011

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

Boost содержит самую известную / широко распространенную версию умных указателей (Seal flavors).

Стандарт C ++ всегда имел своего рода калечащий умный указатель с именем auto_ptr. Это один из предостережений, но полезный сам по себе (RTFM!).

C ++ 0x принимает несколько классов Boost TR1, включая самый популярный интеллектуальный указатель (я надеюсь, что формулирую это правильно, потому что стандарт обычно довольно специфичен в деталях)

НТН

1 голос
/ 06 мая 2011

Помимо того, что вы действительно должны использовать умные указатели (даже непритязательный auto_ptr подойдет для вашей цели), есть возможные проблемы с BODY. Использование потенциально большого раздела кода в качестве аргумента для функционально-подобного макроса имеет свои собственные ловушки. Например, если в BODY есть запятая без скобок, то BODY обращается к двум аргументам. Я не уверен в дальнейших проблемах, потому что я никогда не видел, чтобы кто-нибудь попробовал это.

Не используйте функциональные макросы в C ++. Это редко стоит того.

1 голос
/ 06 мая 2011

Вы ищете шаблон умный указатель . Это стандартный C ++ и подробно объясненный на этом сайте .

0 голосов
/ 07 мая 2011

Может ли этот макрос вызвать некоторые проблемы или вести себя неожиданным образом?

Если BODY выдает исключение, delete будет пропущено.

Решение состоит в том, чтобы использовать идиому RAII. Это одна из самых важных концепций в современном программировании на C ++.

0 голосов
/ 06 мая 2011

Идиоматический способ C ++ делать подобные вещи не с макросами, а с классами «умного указателя», которые используют Получение ресурсов - инициализация .Например, scoped_ptr Boost будет хорошо работать в тех случаях, когда ваш макрос будет иметь смысл.

Я приведу здесь эскиз класса интеллектуальных указателей, но я опускаюмного деталей.Это просто, чтобы дать вам представление о том, как они работают.Вместо этого используйте scoped_ptr, они ничего не пропустили.

template <typename T>
class smartptr<T> {
public:
    smartptr() : ptr(new T) {}
    smartptr(T* p) : ptr(p) {}
    ~smartptr() { delete ptr }
    T& operator*() { return *ptr; }
    T* operator->() { return ptr; }
private:
    T* ptr;
}
0 голосов
/ 06 мая 2011

Я думаю, что лучшим решением было бы использование макроса выделения и удаления вместо всеобъемлющего. Это действительно грязная, не очень полезная вещь

Когда я программирую на C, я обычно делаю что-то вроде следующего:

#define ALLOC_ARY(type, sz) (type*)calloc(sz, sizeof(type))
#define ALLOC_STR(sz) ALLOC_ARY(char, sz)

char *string = ALLOC_STR(128);
int *array = ALLOC_ARY(int, 20);

Но помнить о свободе в vanilla C - это только часть этого:

free(string); string = NULL;
free(array); array = NULL;

Редактировать: Для C ++ умные указатели, как и другие считают, - хороший путь.

0 голосов
/ 06 мая 2011

Похоже, вы хотите выделить объект, выполнить небольшую часть работы с ним, а затем удалить его.Для этого я бы предложил std :: auto_ptr.

...