Mam tendencję do dodawania wielu asercji do mojego kodu C ++, aby ułatwić debugowanie bez wpływu na wydajność kompilacji wydania. Teraz assert
jest czystym makrem C, zaprojektowanym bez uwzględnienia mechanizmów C ++.
Z drugiej strony C ++ definiuje std::logic_error
, który ma być wyrzucany w przypadkach, gdy występuje błąd w logice programu (stąd nazwa). Rzucanie instancji może być po prostu doskonałą, bardziej C ++ alternatywną alternatywą dla assert
.
Problem polega na tym, że assert
i abort
oba kończą program natychmiast bez wywoływania destruktorów, pomijając w ten sposób czyszczenie, podczas gdy ręczne zgłaszanie wyjątku powoduje niepotrzebne koszty działania. Jednym ze sposobów obejścia tego byłoby utworzenie własnego makra asercji SAFE_ASSERT
, które działa tak samo jak odpowiednik w C, ale zgłasza wyjątek w przypadku niepowodzenia.
Przychodzą mi na myśl trzy opinie na ten temat:
- Trzymaj się twierdzenia C. Ponieważ program jest natychmiast przerywany, nie ma znaczenia, czy zmiany zostały poprawnie rozwinięte. Również używanie
#define
s w C ++ jest równie złe. - Wrzuć wyjątek i złap go w main () . Pozwalanie kodowi na pomijanie destruktorów w dowolnym stanie programu jest złą praktyką i należy tego unikać za wszelką cenę, podobnie jak wywołania terminate (). Jeśli rzucane są wyjątki, muszą zostać złapane.
- Zgłoś wyjątek i pozwól mu zakończyć program. Wyjątek kończący program jest w porządku iz tego powodu
NDEBUG
nigdy nie nastąpi to w kompilacji wydania. Przechwytywanie jest niepotrzebne i ujawnia szczegóły implementacji kodu wewnętrznegomain()
.
Czy istnieje ostateczna odpowiedź na ten problem? Jakieś profesjonalne referencje?
Edytowano: pomijanie destruktorów nie jest oczywiście niezdefiniowanym zachowaniem.
logic_error
jest to błąd logiczny. Błąd w logice programu nazywa się błędem. Nie rozwiązujesz błędów, rzucając wyjątki.