Wpis z mikrobloga

#programowanie #qt #cpp

Małe pytanie odnośnie tego co tak właściwie Qt robi podczas emitowania rzeczy jako sygnały.

Mam sobie takiego emita:

emit sendbytearray(Datatosend);

a po nim robię to:

Datatosend.clear();
Datatosend.~QByteArray();

Pytanie brzmi - co się dzieje podczas emitowania? Tutaj jak widać emituję obiekt jako całość. Rozumiem, że adekwatny slot zrobi sobie jego kopię? Co się wtedy dzieje z emitowanym obiektem wewnątrz funkcji emitującej? Czy Qt uznaje go za wysłany i sprząta po sobie (co jest mało prawdopodobne, bo co jakbym chciał coś wyemitować do kilku rzeczy na raz?), czy jednak muszę po sobie posprzątać, bo jak emisja jest w pętli to będzie wesoły wyciek pamięci? Przy czym ten obiekt jest i tak w zakresie działania funkcji i nie jest wklepywany do wskaźnika, więc na koniec wywołania ona sama powinna po sobie posprzątać.
  • 13
@Khaine To zależy od typu połączenia (Direct albo Queued), ale generalnie tak, można założyć że jest to kopiowane. Implementacja prawdopodobnie używa QVariant, więc dlatego w sygnałach nie da się używać obiektów które nie są zarejestrowane dla QMetaTypów.

Pozatym:

Datatosend.~QByteArray();
Ała #!$%@? moje oczy.
@Wiktor426: Napisałem wyżej, że w tym wypadku to jest akurat zbędne, bo jest zakres ważności funkcji. Ale czasem obiekt jest spoza funkcji deklarowany wskaźnikiem (żeby był widoczny poza nim) a wewnątrz funkcji jest tworzony i cośtam jeszcze się dzieje z nim. No i dzieje się to cyklicznie, więc za każdym razem tworzony jest pod tym wskaźnikiem nowy obiekt. W takim wypadku chyba wypada posprzątać po nim zanim się stworzy nowy, nie?
@Khaine: jeżeli przekazujesz do funkcji obiekt który jest wskaźnikiem i po wywołaniu funkcji wraca do funkcji to robisz po prostu delete wsk; i wtedy wywoływany jest destruktor. Wydaję mi się że musisz powtórzyć wiedzę o przekazywaniu argumentów do funkcji.
@Wiktor426: Tak, wiem. Dlatego napisałem, że to jest zbędne. Funkcja sama rozwali wszystko co ma w środku.

Swoją drogą jak już tu jesteś - jak wymusić na QTcpSockecie informację o tym, że się połączył ale bez wysyłania żadnych danych? W sensie Socket grzecznie mi emituje sygnał Connected, ale dopiero wtedy jak jakieś dane przez niego przejdą. Jeśli serwer tylko spiknie dwa sockety ze sobą, ale nie zostaną przesłane żadne dane, to
@Khaine: nie jest zbędne. Jest szkodliwe. Dwukrotne wykonanie destruktora na tym samym obiekcie to de facto wykonanie destruktora na nieistniejącym obiekcie. To UB.

@lionbest: Ƶaden QVariant, po to rejestrujesz typy, ƶeby Qt bez tego umiało sobie poradzić.

QByteArray, jak i większość (wszystkie?) kontenery Qt jest współdzielony, więc tworzona jest tylko płytka kopia (tak naprawdę kopiowany jest tylko wskaźnik na dane, którego refcount rośnie).

a emit to tylko cukier
@KrzaQ2: Przejrzałem kod Qt5.6 na szybko i masz rację, w przypadku DirectConnection i BlockingQueuedConnection przekazywane są tylko wskaźniki, a w przypadku QueuedConnection używane jest QMetaType::create do stworzenia kopii każdego z argumentów.