0Pricing
C++ Academy · Lekcja

Strażnicy zakresu

Wykonuj sprzątanie przy opuszczaniu zakresu

Strażnicy zakresu to bezpłatna lekcja C++ Academy na CoddyKit. To lekcja 4 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej C++ Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs C++ Academy zawiera 4 lekcji w sumie.

Czym jest strażnik zakresu

Strażnik zakresu to obiekt RAII, którego jedynym zadaniem jest wykonanie czynności porządkowej po wyjściu z zakresu — nawet po wcześniejszym zwrocie lub zgłoszeniu wyjątku.

Problem, który rozwiązuje

Bez strażnika łatwo zapomnieć o sprzątaniu po wcześniejszym return lub throw. Strażnik zakresu wykonuje tę czynność automatycznie.

lock_guard: standardowy strażnik zakresu

std::lock_guard blokuje muteks podczas tworzenia i odblokowuje go podczas niszczenia — jest wbudowanym strażnikiem zakresu dla blokad.

#include <mutex>

std::mutex m;

void critical() {
    std::lock_guard<std::mutex> lk(m);   // locked
    // ... work ...
}                                        // unlocked automatically

Własnoręcznie napisany strażnik

Mogą Państwo napisać strażnika, który przechowuje funkcję i wywołuje ją w destruktorze.

#include <iostream>
#include <functional>

class ScopeGuard {
    std::function<void()> fn;
public:
    ScopeGuard(std::function<void()> f) : fn(std::move(f)) {}
    ~ScopeGuard() { fn(); }
};

int main() {
    ScopeGuard g([] { std::cout << "cleanup\n"; });
    std::cout << "work\n";
}

Sprzątanie po wcześniejszym return

Ponieważ destruktor jest wywoływany przy opuszczaniu zakresu, czynność strażnika zostanie wykonana niezależnie od tego, w jaki sposób funkcja kończy działanie.

#include <iostream>
#include <functional>

class ScopeGuard {
    std::function<void()> fn;
public:
    ScopeGuard(std::function<void()> f) : fn(std::move(f)) {}
    ~ScopeGuard() { fn(); }
};

void run(bool stop) {
    ScopeGuard g([] { std::cout << "always cleaned\n"; });
    if (stop) return;
}

int main() { run(true); }

Sprzątanie po zgłoszeniu wyjątku

Jeśli wyjątek rozwija stos przez dany zakres, destruktor strażnika nadal zostanie wywołany, bezpiecznie zwalniając zasób.

Anulowanie działania strażnika

Czasami chcą Państwo pominąć sprzątanie, ponieważ operacja zakończyła się powodzeniem. Rzeczywiste strażniki udostępniają funkcję dismiss(), która wyłącza tę czynność.

#include <iostream>
#include <functional>

class ScopeGuard {
    std::function<void()> fn;
    bool active = true;
public:
    ScopeGuard(std::function<void()> f) : fn(std::move(f)) {}
    void dismiss() { active = false; }
    ~ScopeGuard() { if (active) fn(); }
};

int main() {
    ScopeGuard g([] { std::cout << "rollback\n"; });
    g.dismiss();   // success: no rollback
}

Zastosowanie do wycofywania zmian

Strażniki zakresu doskonale sprawdzają się w kodzie transakcyjnym: należy zarejestrować czynność wycofania zmian, wykonać operację, a po pomyślnym zakończeniu wyłączyć strażnika.

Strażniki są wyłącznie przenoszalne

Strażnika nie należy kopiować — kopiowanie spowodowałoby dwukrotne wykonanie czynności. Strażniki powinny być wyłącznie przenoszalne albo niekopiowalne.

Standardowe i biblioteczne narzędzia pomocnicze

std::scoped_lock chroni wiele muteksów, a biblioteki takie jak GSL udostępniają funkcję finally. Wiele baz kodu zawiera niewielkie narzędzie ScopeGuard.

Preferowanie wyspecjalizowanych typów RAII

Gdy istnieje dedykowany typ RAII (lock_guard, unique_ptr, fstream), należy go preferować. Ogólnego strażnika zakresu należy używać tylko do doraźnego sprzątania, dla którego nie istnieje naturalne opakowanie.

Szybkie sprawdzenie

Proszę sprawdzić swoją znajomość strażników zakresu.

Podsumowanie

Poznali Państwo zasadę, że strażnik zakresu automatycznie wykonuje sprzątanie przy opuszczaniu zakresu dzięki RAII. Obsługuje wcześniejsze zwroty i wyjątki, umożliwia wycofywanie zmian za pomocą dismiss() i powinien być wyłącznie przenoszalny. Gdy istnieją dedykowane typy RAII, należy je preferować.

Często zadawane pytania

Czy lekcja „Strażnicy zakresu” jest bezpłatna?

Tak — pełny tekst „Strażnicy zakresu” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu C++ Academy, przejdź na CoddyKit PRO. Kurs C++ Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Strażnicy zakresu”?

Wykonuj sprzątanie przy opuszczaniu zakresu Ćwiczysz C++ Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć C++ Academy?

Nie wymagamy żadnego doświadczenia. C++ Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 4 z 4.

Ile czasu zajmuje lekcja „Strażnicy zakresu”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji C++ Academy?

Tak. Każda lekcja C++ Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Zasada RAII
  2. Destruktory i sprzątanie
  3. Reguła trzech/pięciu
  4. Strażnicy zakresu
← Powrót do C++ Academy