operator new w argumencie funkcji

0

Przyjmijmy, że mam funkcję:

void f(const X *){}

i wywołuję gdzieś dalej:

f(new X())

Czy(ew. kiedy) obiekt stworzony przez new zostanie usunięty?

1

Jak go wprost usuniesz (delete), to zostanie usunięty. Jak nie to dojdzie do wycieku pamięci.

1

Nie. Musi zostać wywołany operator delete. Może być on wywołany niekoniecznie przez ciebie, ale przez np. smart pointer (np. std::unique_ptr).

1

Gdy wywołasz delete na wskaźniku do niego. https://dsp.krzaq.cc/post/176/ucze-sie-cxx-kiedy-uzywac-new-i-delete/

0

Ale gdzie i jak mam go usunąć? X wspomniany wcześniej to klasa, więc nie ma tu wskaźnika... Chyba, że w funkcji f jeśli nie będzie mi już potrzebny, tak?

0

Właśnie dlatego nie powinieneś używać wskaźników praktycznie nigdy.

0

Może wytłumaczę dokładniej, bo chciałem użyć unique_ptr właśnie, ale wtedy funkcja nie działała. Chodzi o Qt i sprawienie aby QLineEdit przyjmował tylko liczby rzeczywiste dodatnie. Znalazłem na SO:

ui.lineEdit_weight->setValidator(new QDoubleValidator(0, 100, 2, this));

To mi działa, chociaż można wpisać wartości większe niż 100... Ale, że naczytałem się na tym forum(szczególnie od @kq), żeby nie używać gołych wskaźników, to dałem coś takiego:

std::unique_ptr<QDoubleValidator> qvalidator{ new QDoubleValidator(0, 100, 2, this) };
ui.lineEdit_distance->setValidator(qvalidator.get());

To już mi nie działa...

Jak to zrobić poprawnie?

0

Pod koniec funkcji możesz zwolnić wskaźnik i gitara.

0

Ok, udało mi się w "Kompendium wiedzy C++" znaleźć:

std::unique_ptr<QDoubleValidator> qvalidator{ new QDoubleValidator(0, 100, 2, this) };
ui.lineEdit_distance->setValidator(qvalidator.release());

Działa, ale w sumie nie wiem czemu dokładnie, więc jak można prosić o wytłumaczenie, będę wdzięczny ;)

2
fryderykst napisał(a):
std::unique_ptr<QDoubleValidator> qvalidator{ new QDoubleValidator(0, 100, 2, this) };
ui.lineEdit_distance->setValidator(qvalidator.get());

To już mi nie działa...

Jak to zrobić poprawnie?

Najprościej - to tak:

  1. w obiekcie ui poza funkcjami dodajesz to:
std::unique_ptr<QDoubleValidator> qvalidator{ new QDoubleValidator(0, 100, 2, this) };
  1. tam gdzie ten kod miałeś:
ui.lineEdit_distance->setValidator(qvalidator.get());

Wyjaśnienie:
Zakładając że "ui" jest właścicielem kontrolki lineEdit_distance, qvalidator powinien istnieć tak długo jak ui, dlatego jeśli dodasz qvalidator jako pole w klasie, wszystko powinno być OK.
Aktualnie masz tak:

  • budujesz walidator
  • przypisujesz do kontrolki
  • usuwasz walidator z pamięci
  • kontrolka próbuje użyć walidatora
  • otrzymujesz efekt "nie działa"
1

stare C++ bez wycieku:

void f(const X *){}

X x;
f(&x);

C++14

void f(const X *){}

f(std::make_unique<X>().get());

albo

void f(std::unique_ptr<X>&&){}

f(std::make_unique<X>());

W Qt masz masz zarządzanie pamięcią za pomocą drzewa i relacji rodzic dziecko, przykładowo to: ```ccp new QDoubleValidator(0, 100, 2, this) ``` Tworzy obiekt `QDoubleValidator` którego właścicielem (rodzicem) jest obiekt wskazywany przez `this` (przypuszczalnie `MainWindow`). W tym wypadku jak tylko `MainWindow` zostanie usuniete to wraz z nim QDoubleValidator pójdzie do piachu.

Wcześniejsza odpowiedź w której mieszany jest mechanizm rodzić-dziecko z Qt z std::unique_ptr<QDoubleValidator>, grozi crashem jeśli rodzic zginie przed std::unique_ptr<QDoubleValidator> (wtedy unique_ptr będzie wskazywał na martwy obiekt).
Sprzątanie w odwrotnej kolejności nie kończy się crashem bo usunięcie QObject (za pomocą unique_ptr) automatycznie usuwa go z drzewa - rodzić jest notyfikowany o śmierci dziecka i usuwany z listy obiektów do usunięcia.

1 użytkowników online, w tym zalogowanych: 0, gości: 1