Menu
Coddy logo textTech

RAII w C++

Część sekcji Programowanie obiektowe ścieżki C++ w Coddy. Lekcja 16 z 104.

RAII (Resource Acquisition Is Initialization) to podstawowy idiom C++, w którym zarządzanie zasobami jest powiązane z czasem życia obiektu. Pomysł jest prosty: pozyskuj zasoby w konstruktorze, zwalniaj je w destruktorze.

Gdy obiekt zostaje utworzony, uzyskuje wszystkie potrzebne mu zasoby. Gdy obiekt wychodzi poza zakres, jego destruktor automatycznie zwalnia te zasoby. Gwarantuje to sprzątanie nawet w przypadku wystąpienia wyjątków.

class FileHandler {
    std::FILE* file;
public:
    FileHandler(const char* filename) {
        file = std::fopen(filename, "r");  // Pozyskaj zasób
    }
    
    ~FileHandler() {
        if (file) std::fclose(file);       // Zwolnij zasób
    }
};

Dzięki RAII nigdy nie zapomnisz o sprzątaniu:

void processFile() {
    FileHandler handler("data.txt");  // Zasób został pozyskany
    // Praca z plikiem...
    // Jeśli tutaj zostanie zgłoszony wyjątek, destruktor i tak zostanie wywołany!
}   // Zasób zostaje automatycznie zwolniony

Inteligentne wskaźniki są doskonałym przykładem RAII w praktyce. unique_ptr przejmuje własność pamięci sterty w konstruktorze i usuwa ją w destruktorze. Korzystasz już z RAII, nawet o tym nie wiedząc!

RAII ma zastosowanie do dowolnych zasobów: pamięci, uchwytów plików, połączeń sieciowych, muteksów lub połączeń z bazą danych. Opakowując zasoby w obiekty, C++ zapewnia deterministyczne sprzątanie i eliminuje całe kategorie błędów, takich jak wycieki i wiszące uchwyty.

challenge icon

Wyzwanie

Łatwy

Zbudujmy menedżer połączeń, który demonstruje RAII, automatycznie obsługując cykl życia połączeń podobnych do sieciowych. Gdy połączenie zostaje utworzone, powinno się „otworzyć”, a gdy wyjdzie poza zakres, powinno się automatycznie „zamknąć”: nie jest wymagane ręczne sprzątanie!

Utworzysz dwa pliki, aby uporządkować swój kod:

  • Connection.h: Zdefiniuj klasę Connection, która zarządza zasobem połączenia zgodnie z zasadami RAII. Klasa powinna mieć:
    • Prywatny atrybut connectionId (string) służący do identyfikowania połączenia
    • Prywatny atrybut isOpen (bool) służący do śledzenia stanu połączenia
    • Konstruktor, który przyjmuje identyfikator połączenia, ustawia isOpen na true i wyświetla "Opening connection: <id>"
    • Destruktor, który sprawdza, czy połączenie jest otwarte, zamyka je, ustawiając isOpen na false, i wyświetla "Closing connection: <id>"
    • Metodę send(string message), która wyświetla "[<id>] Sending: <message>", jeśli połączenie jest otwarte
    • Metodę getId(), która zwraca identyfikator połączenia
  • main.cpp: Zademonstruj, jak RAII zapewnia automatyczne sprzątanie, odczytując z wejścia identyfikator połączenia i wiadomość. Następnie:
    • Utwórz zakres za pomocą nawiasów klamrowych { }
    • W tym zakresie utwórz na stosie obiekt Connection z wprowadzonym identyfikatorem
    • Użyj połączenia, aby wysłać wprowadzoną wiadomość
    • Pozwól zakończyć się zakresowi (połączenie powinno zamknąć się automatycznie)
    • Poza zakresem wyświetl "Connection out of scope"

Piękno RAII polega na tym, że nie musisz pamiętać o zamknięciu połączenia: destruktor obsługuje to automatycznie, gdy obiekt opuszcza zakres. Ten wzorzec zapobiega wyciekom zasobów, nawet jeśli w twoim kodzie wydarzy się coś nieoczekiwanego.

Dołącz plik nagłówkowy w main.cpp za pomocą #include "Connection.h".

Spróbuj swoich sił

#include <iostream>
#include <string>
#include "Connection.h"

using namespace std;

int main() {
    string connectionId;
    string message;
    
    // Wczytaj dane wejściowe
    cin >> connectionId;
    cin.ignore();
    getline(cin, message);

    // TODO: Utwórz zakres za pomocą nawiasów klamrowych { }
    // Wewnątrz zakresu:
    //   - Utwórz na stosie obiekt Connection z connectionId
    //   - Użyj połączenia, aby wysłać wiadomość
    // Pozwól, aby zakres się zakończył (destruktor zostanie wywołany automatycznie)

    // TODO: Po zakończeniu zakresu wypisz "Connection out of scope"

    return 0;
}
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator C++ online