2013-10-14 2 views
2

В проекте Qt У меня есть методQt удаление метод указатель

void ProtocolHandler::interpretData(uint8_t packet_id){ 
    PacketClass *packet = new RSP2StatusPacket(_packet_buf); 
    emit packetReceived(packet); 
} 

где я объявить объект пакет типа PacketClass, а затем я испустить сигнал

packetReceived (PacketClass*) 

В другом классе у меня есть следующий слот:

void ReceiverCommands::processReceivedPacket(PacketClass* pkt) 
{ 
    status_packet *payload = pkt->getPayload(); 

    delete pkt 
} 

Правильно ли удалить новый пакет PacketClass * в методе слота? Иногда моя программа вылетает так, что лучший способ удалить указатель, переданный в сигнале/слоте (я полагаю, я должен удалить pkt, потому что я создаю новый пакет в методе «interpradata»).

+0

вы не должны делать этого, что, если есть несколько слотов, подключенных к этому сигналу (или даже двойное подключение) –

+0

В случае PacketClass не производном от QObject, я хотел бы попробовать какой-то подход с использованием оболочки class и QSharedPointer, чтобы убедиться в удалении объекта, когда все слоты завершат обработку. В другом случае ответ Merlin069 правильный. – Jairo

+0

@Jairo: Зачем вам нужен класс-обертка? –

ответ

1

Предполагая PacketClass является производным от QObject, то вызовите функцию deleteLater: -

pkt->deleteLater(); 

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

Смотрите документацию для deleteLater here, которая также имеет отношение к Qt4

+1

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

+0

Вы также неясны относительно *, где * следует вызывать 'deleteLater' - было бы разумно делать это только в сигнале, а не в слотах. Как минимум, вам нужно будет передать QPointer, чтобы, если кто-то злоупотребляет этим кодом и прикрепляет его к слоту в другом потоке, этот поток не будет иметь свисающего указателя, но сможет изящно свернуть, - определение проблемы. –

+0

Или, по крайней мере, вам нужно переопределить 'connectNotify' в' ProtocolHandler' и отслеживать подключенные объекты, чтобы убедиться, что они не находятся в неправильном потоке (или перемещены в неправильный поток!). –

2

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

Вы должны пройти QSharedPointer<PacketClass> и использовать его. Он будет делать удаление по мере необходимости.

typedef QSharedPointer<PacketClass> PacketClassPtr; 
Q_DECLARE_METATYPE(PacketClassPtr) 

ProtocolHandler { 
    ... 
    Q_SIGNAL void packetReceived(PacketClassPtr packet); 
} 

void ProtocolHandler::interpretData(uint8_t packet_id){ 
    PacketClassPtr packet(new RSP2StatusPacket(_packet_buf)); 
    emit packetReceived(packet); 
} 

void ReceiverCommands::processReceivedPacket(PacketClassPtr pkt) 
{ 
    status_packet *payload = pkt->getPayload(); 
} 
Смежные вопросы