User 13204940 Ответов: 3

Немного запутанная ситуация с указателем


Привет,

Я не совсем уверен, как работают указатели в этой ситуации, которую я создал, и я стараюсь избегать утечек памяти. Я написал следующий код;

Packet* packet;

// construct packet from ID and data
switch (packet_id)
{
case 0:
	PacketPlayerMove* p = new PacketPlayerMove();
	// call some methods on p here which aren't present in base class Packet
	packet = p;
}

return packet;

Таким образом, PacketPlayerMove и многие другие являются реализациями пакета базового класса. Этот метод возвращает пакет*, поэтому я создаю пакет* и присваиваю его значение в качестве экземпляра любого из наследующих классов в зависимости от уникального идентификатора packet_id.

В двух словах:

packet_id 0: return PacketPlayerMove
packet_id 1: возврат PacketPlayerChat
и т.д.

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

Я буду удалять packet позже, но я не знаю, должен ли я удалить p сейчас, или это не нужно удалять.

Что я уже пробовал:

-----------------------------------------------

Richard MacCutchan

Если вы удалите p перед возвращением из этой функции, то пакет больше не будет действителен. У вас есть только один фактический блок памяти, но оба p и packet указывают на него.

3 Ответов

Рейтинг:
2

CPallini

Вы также можете взглянуть на C++ умные указатели, см., например вступление/умные указатели - cppreference.com[^].


Рейтинг:
0

Rick York

Если вы собираетесь удалить указатель позже, то вы не должны удалять его "сейчас". Если вы скопировали его, то, скорее всего, у вас будет утечка памяти. Вы должны быть в состоянии проверить это и обнаружить утечку памяти. Я использую макрос "#define new DEBUG_NEW" повсюду, и утечки обнаруживаются в режиме отладки.


[no name]

Я имею в виду packet будет удален позже, но я не уверен, стоит ли удалять p сейчас или нет. p используется только для вызова методов реализации, а не базового класса.

Я также получаю тонну ошибок, жалующихся на то, что DEBUG_NEW не определен.

Rick York

Я использую MFC и считаю, что DEBUG_NEW поставляется вместе с ним. Если вы не используете MFC, то этот макрос, вероятно, вам недоступен. Однако может быть доступна какая-то другая функция распределения отслеживания памяти. Если вы уверены, что p будет удален позже, то не удаляйте его там, если объект не был скопирован. В противном случае вы попытаетесь получить доступ к недопустимым данным, и возникнет исключение.

Рейтинг:
0

KarstenK

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

//some normal int var
int a = 2;
int b = a;

PacketPlayerMove* p = new PacketPlayerMove();//Pointer value NEEDS a delete
PacketPlayerMove* p2 = p;//no new instance only pointer assigment, so both pointers are pointing to the SAME address

delete p;// free the memory.
Узнайте больше об указателях в этом разделе Учебник по C++ В нем есть несколько интересных глав, наполненных интересными знаниями.

Лучше всего писать ясный и понятный код, потому что при работе с большим количеством указателей многое может пойти не так.


[no name]

Таким образом, это означает, что я могу удалить либо пакет, либо p и освободить память.

С помощью PHP можно удалить, используя обычные переменные unset(..) освободить память. Будет ли эквивалент здесь заключаться в том, чтобы установить p2 к нулю, а затем удалить p?

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