Zrozumienie znaczenia terminu i pojęcia - RAII (pozyskiwanie zasobów jest inicjalizacją)

Czy moglibyście dać nam dobry opis czym jest RAII, dlaczego jest on ważny i czy może mieć jakiekolwiek znaczenie dla innych języków?

I do wiem trochę. Wierzę, że to oznacza "pozyskiwanie zasobów jest Inicjalizacja". Jednak nazwa ta nie współgra z moim (prawdopodobnie niepoprawnym) zrozumieniem czym jest RAII: odnoszę wrażenie, że RAII jest sposobem inicjalizacji obiektów na stosie tak, że gdy te zmienne wyjdą z scope, destruktory zostaną automatycznie wywołane, powodując czyszczenie zasobów.

Więc dlaczego nie nazywa się to "używanie stosu do wyzwalania czyszczenia" (UTSTTC:)? Jak się stamtąd dostać do "RAII"?

A jak można zrobić coś na stosie, co spowoduje oczyszczenie czegoś, co żyje na stosie? Są też przypadki, w których nie możesz użyć RAII? Czy kiedykolwiek marzyłeś o zbieraniu śmieci? Przynajmniej śmieciarka, której mógłbyś użyć do niektórych obiektów pozwalając innym być zarządzanym?

Dzięki.
Author: Aquarius_Girl, 2009-04-03

11 answers

Więc dlaczego nie nazywa się to "używanie stosu do wyzwalania czyszczenia" (UTSTTC:)?

RAII mówi ci, co masz robić: Zdobądź swój zasób w konstruktorze! Dodałbym: jeden zasób, jeden konstruktor. UTSTTC jest tylko jednym z zastosowań tego, RAII jest znacznie więcej.

Zarządzanie zasobami jest do bani. tutaj zasoby to wszystko, co wymaga czyszczenia po użyciu. Badania projektów na wielu platformach pokazują, że większość błędów jest związana z zarządzaniem zasobami - i jest to szczególnie złe w systemie Windows (ze względu na wiele rodzajów obiektów i alokatorów).

W C++ zarządzanie zasobami jest szczególnie skomplikowane ze względu na kombinację wyjątków i szablonów (styl C++). Aby zajrzeć pod maskę, zobacz GOTW8).


C++ gwarantuje, że Destruktor zostanie wywołany wtedy i tylko wtedy, gdy konstruktor się powiedzie. Opierając się na tym, RAII może rozwiązać wiele paskudnych problemów, których przeciętny programista może nawet nie być świadomy. Oto kilka przykładów poza "moje zmienne lokalne zostaną zniszczone za każdym razem, gdy wrócę".

Zacznijmy od zbyt uproszczonej FileHandle klasy używającej RAII:

class FileHandle
{
    FILE* file;

public:

    explicit FileHandle(const char* name)
    {
        file = fopen(name);
        if (!file)
        {
            throw "MAYDAY! MAYDAY";
        }
    }

    ~FileHandle()
    {
        // The only reason we are checking the file pointer for validity
        // is because it might have been moved (see below).
        // It is NOT needed to check against a failed constructor,
        // because the destructor is NEVER executed when the constructor fails!
        if (file)
        {
            fclose(file);
        }
    }

    // The following technicalities can be skipped on the first read.
    // They are not crucial to understanding the basic idea of RAII.
    // However, if you plan to implement your own RAII classes,
    // it is absolutely essential that you read on :)



    // It does not make sense to copy a file handle,
    // hence we disallow the otherwise implicitly generated copy operations.

    FileHandle(const FileHandle&) = delete;
    FileHandle& operator=(const FileHandle&) = delete;



    // The following operations enable transfer of ownership
    // and require compiler support for rvalue references, a C++0x feature.
    // Essentially, a resource is "moved" from one object to another.

    FileHandle(FileHandle&& that)
    {
        file = that.file;
        that.file = 0;
    }

    FileHandle& operator=(FileHandle&& that)
    {
        file = that.file;
        that.file = 0;
        return *this;
    }
}

Jeśli konstrukcja zawiedzie (z wyjątkiem), żadna inna funkcja członka-nawet Destruktor-nie zostanie wywołana.

RAII unika używania obiektów w stanie nieprawidłowym.To już ułatwia życie, zanim w ogóle użyjemy obiektu.

[[19]}teraz spójrzmy na tymczasowe obiekty:
void CopyFileData(FileHandle source, FileHandle dest);

void Foo()
{
    CopyFileData(FileHandle("C:\\source"), FileHandle("C:\\dest"));
}

Istnieją trzy przypadki błędów: nie można otworzyć żadnego pliku, można otworzyć tylko jeden plik, oba pliki można otworzyć, ale kopiowanie plików nie powiodło się. W implementacji innej niż RAII, Foo musiałaby zająć się wszystkimi trzema przypadkami jawnie.

RAII uwalnia zasoby, które zostały nabyte, nawet jeśli wiele zasobów zostało nabranych w ramach jednego Oświadczenia.

Teraz zagregujmy niektóre obiekty:

class Logger
{
    FileHandle original, duplex;   // this logger can write to two files at once!

public:

    Logger(const char* filename1, const char* filename2)
    : original(filename1), duplex(filename2)
    {
        if (!filewrite_duplex(original, duplex, "New Session"))
            throw "Ugh damn!";
    }
}

Konstruktor Logger będzie niepowodzenie, jeśli konstruktor original nie powiedzie się (ponieważ filename1 nie można otworzyć), konstruktor duplex nie powiedzie się (ponieważ filename2 nie można otworzyć) lub zapis do plików wewnątrz konstruktora Logger nie powiedzie się. W każdym z tych przypadków, Destruktor Logger będzie wywoływany , a nie - więc nie możemy polegać na destruktorze Logger, aby zwolnić pliki. Ale jeśli original został zbudowany, jego Destruktor zostanie wywołany podczas czyszczenia konstruktora Logger.

RAII upraszcza sprzątanie po częściowym Budownictwo.


Punkty ujemne:

Punkty ujemne? Wszystkie problemy można rozwiązać za pomocą RAII i inteligentnych wskaźników; -) {]}

RAII jest czasami nieporęczny, gdy potrzebujesz opóźnionego przejęcia, pchając zagregowane obiekty na stertę.
Wyobraź sobie, że rejestrator potrzebuje SetTargetFile(const char* target). W takim przypadku uchwyt, który nadal musi być członkiem Logger, musi znajdować się na stercie (np. w inteligentnym wskaźniku, aby wywołać zniszczenie uchwytu odpowiednio.)

Nigdy nie życzyłem sobie zbierania śmieci. Kiedy robię C# czasami czuję chwilę błogości, że po prostu nie muszę się przejmować, ale znacznie bardziej Tęsknię za wszystkimi fajnymi zabawkami, które można stworzyć poprzez deterministyczną destrukcję. (using IDisposable just doesn ' t cut it.)

Miałem jedną szczególnie złożoną strukturę, która mogła skorzystać z GC, gdzie "proste" inteligentne wskaźniki powodowałyby okrągłe odwołania do wielu klas. My muddled through by ostrożnie balansując silne i słabe wskaźniki, ale za każdym razem, gdy chcemy coś zmienić, musimy przestudiować duży Wykres relacji. GC mogło być lepsze, ale niektóre komponenty posiadały zasoby, które powinny zostać wydane jak najszybciej.


Uwaga na próbce FileHandle: nie miała być kompletna, tylko próbka-ale okazała się niepoprawna. Dzięki Johannes Schaub za wskazanie i FredOverflow za przekształcenie go w poprawne rozwiązanie C++0x. Z czasem ustatkowałem się z podejście udokumentowane tutaj .

 127
Author: peterchen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-11-22 08:42:23

Tam są doskonałe odpowiedzi, więc dodam tylko kilka rzeczy zapomnianych.

0. RAII jest o lunetach

RAII jest o obu:

  1. pozyskiwanie zasobu (bez względu na zasób) w konstruktorze, a od-pozyskiwanie go w destruktorze.
  2. wywołanie konstruktora, gdy zmienna jest zadeklarowana, a Destruktor zostanie wykonany automatycznie, gdy zmienna wyjdzie poza zakres.

Inni już na to odpowiedzieli, więc ja Nie będę się rozwijał.

1. Podczas kodowania w Javie lub C#, używasz już RAII...

Co? Kiedy mówię: "Nicole, przynieś mi moje pantofle., "to proza? Mistrz filozofii: tak jest. [17]} MONSIEUR JOURDAIN: od ponad czterdziestu lat mówię prozą, nie wiedząc nic o tym, i jestem zobowiązany do ciebie za to, że mnie tego nauczyłeś.

- Moliere: Klasa Średnia Gentleman, Akt 2, Scena 4

Jak Monsieur Jourdain zrobił z proza, C#, a nawet Java ludzie już używają RAII, ale w ukryty sposób. Na przykład poniższy kod Javy (który jest napisany w ten sam sposób w C# przez zastąpienie synchronizedlock):

void foo()
{
   // etc.

   synchronized(someObject)
   {
      // if something throws here, the lock on someObject will
      // be unlocked
   }

   // etc.
}

... używa już RAII: akwizycja mutex jest wykonywana w słowie kluczowym (synchronized lub lock), a un-akwizycja zostanie wykonana po wyjściu z zakresu.

Jest tak naturalny w swojej notacji, że wymaga prawie nie Wyjaśnienie nawet dla ludzi, którzy nigdy nie słyszeli o RAII.

Przewaga C++ nad Javą i C# polega na tym, że wszystko można zrobić za pomocą RAII. Na przykład, nie ma bezpośredniego odpowiednika synchronized ani lock W C++, ale nadal możemy je mieć.

W C++ byłoby napisane:

void foo()
{
   // etc.

   {
      Lock lock(someObject) ; // lock is an object of type Lock whose
                              // constructor acquires a mutex on
                              // someObject and whose destructor will
                              // un-acquire it 

      // if something throws here, the lock on someObject will
      // be unlocked
   }

   // etc.
}

Które można łatwo zapisać w sposób Java / C# (używając makr C++):

void foo()
{
   // etc.

   LOCK(someObject)
   {
      // if something throws here, the lock on someObject will
      // be unlocked
   }

   // etc.
}

2. RAII mają alternatywne zastosowania

WHITE RABBIT: [śpiew] jestem spóźniony / I ' m spóźniony / na bardzo ważną datę. / Nie ma czasu, by się przywitać."/Do widzenia. / Jestem spóźniony, jestem spóźniony, jestem spóźniony.

- Alicja w Krainie Czarów (Wersja Disneya, 1951)

Wiesz, kiedy zostanie wywołany konstruktor (przy deklaracji obiektu), i wiesz, kiedy zostanie wywołany odpowiadający mu Destruktor( przy wyjściu z zakresu), więc możesz napisać prawie magiczny Kod tylko za pomocą linii. Witam w Krainie Czarów C++ (przynajmniej od programisty C++ punkt widzenia).

Na przykład, możesz napisać obiekt counter (pozwolę sobie to jako ćwiczenie) i użyć go po prostu deklarując jego zmienną, tak jak powyższy obiekt lock został użyty:

void foo()
{
   double timeElapsed = 0 ;

   {
      Counter counter(timeElapsed) ;
      // do something lengthy
   }
   // now, the timeElapsed variable contain the time elapsed
   // from the Counter's declaration till the scope exit
}

Które oczywiście można zapisać ponownie, w sposób Java / C# przy użyciu makra:

void foo()
{
   double timeElapsed = 0 ;

   COUNTER(timeElapsed)
   {
      // do something lengthy
   }
   // now, the timeElapsed variable contain the time elapsed
   // from the Counter's declaration till the scope exit
}

3. Dlaczego w C++ brakuje finally?

[krzyki] to finał odliczanie!

- Europe: The Final Countdown (sorry, I was out of quotes, here... :-)

Klauzula finally jest używana w C#/Java do obsługi usuwania zasobów w przypadku wyjścia z zakresu (poprzez return lub wyrzucony wyjątek).

Bystrzy czytelnicy specyfikacji zauważą, że C++ nie ma w końcu klauzuli. I to nie jest błąd, ponieważ C++ go nie potrzebuje, ponieważ RAII już zajmuje się utylizacją zasobów. (A uwierz mi, pisanie destruktora C++ jest łatwiejsze niż pisanie właściwej klauzuli Javy, czy nawet poprawnego C# metoda).

Ale czasami klauzula finally byłaby fajna. Możemy to zrobić w C++? Tak, możemy! i ponownie z alternatywnym użyciem RAII.

RAII to coś więcej niż Filozofia W C++: to C++
RAII? TO JEST C++!!!

- w 2007 roku, po raz pierwszy w historii Sparty, został wybrany na jednego z najlepszych graczy w historii Sparty.]}

Kiedy osiągniesz jakiś poziom doświadczenia w C++, zaczynasz myśleć w termin RAII , w terminach constratorów i destruktorów automatycznej realizacji .

Zaczynasz myśleć w kategoriach zakresów , A znaki { i } stają się jednymi z najważniejszych w Twoim kodzie.

I prawie wszystko pasuje do RAII: bezpieczeństwo WYJĄTKÓW, muteksy, połączenia baz danych, żądania baz danych, połączenie z serwerem, Zegary, uchwyty systemu operacyjnego itp. i ostatnia, ale nie mniej ważna, pamięć.

Część bazy danych nie jest pomijalne, ponieważ, jeśli akceptujesz zapłacić cenę, możesz nawet napisać w stylu " programowanie transakcyjne ", wykonując linie i linie kodu, aż w końcu zdecydujesz, czy chcesz zatwierdzić wszystkie zmiany, lub, jeśli nie jest to możliwe, że wszystkie zmiany zostaną cofnięte (o ile każda linia spełnia co najmniej silną gwarancję wyjątku). (zobacz drugą część tego artykułu Suttera Herba {[91] } dla programowania transakcyjnego).

I jak puzzle, wszystko pasuje.

RAII jest tak bardzo częścią C++, że bez niego C++ nie mógłby być C++.

To wyjaśnia, dlaczego doświadczeni programiści C++ są tak zakochani w RAII i dlaczego RAII jest pierwszą rzeczą, której szukają, próbując innego języka.

I to wyjaśnia, dlaczego Garbage Collector, będąc świetną technologią samą w sobie, nie jest tak imponujący z punktu widzenia programisty C++:

    RAII zajmuje się już większością spraw prowadzonych przez GC.]}
  • A GC obsługuje lepiej niż RAII z okrągłymi referencjami na czystych zarządzanych obiektach (łagodzone przez inteligentne użycie słabych wskaźników)
  • nadal GC jest ograniczone do pamięci, podczas gdy RAII może obsłużyć każdy rodzaj zasobów.
  • jak opisano powyżej, RAII może zrobić dużo, dużo więcej...
 42
Author: paercebal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-19 21:24:40
 16
Author: Mitch Wheat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:17:54

RAII używa semantyki destruktorów C++ do zarządzania zasobami. Na przykład rozważ inteligentny wskaźnik. Masz sparametryzowany konstruktor wskaźnika, który inicjalizuje ten wskaźnik za pomocą adresu obiektu. Przypisujesz wskaźnik na stosie:

SmartPointer pointer( new ObjectClass() );

Gdy inteligentny wskaźnik wyjdzie poza zakres, Destruktor klasy pointer usunie podłączony obiekt. Wskaźnik jest alokowany przez stos, a obiekt-sterta-alokowany.

Są pewne przypadki, kiedy RAII nie pomaga. Na przykład, jeśli używasz inteligentnych wskaźników zliczających odniesienia (takich jak boost::shared_ptr) i tworzysz strukturę podobną do wykresu z cyklem, ryzykujesz wyciek pamięci, ponieważ obiekty w cyklu zapobiegną wzajemnemu zwolnieniu. Zbiórka śmieci pomoże temu zapobiec.
 10
Author: sharptooth,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-03 05:34:29

Zgadzam się z CP. Ale chciałbym dodać, że zasoby mogą być wszystko, nie tylko pamięć. Zasobem może być plik, sekcja krytyczna, wątek lub połączenie z bazą danych.

Nazywa się Akwizycja zasobów jest inicjalizacją, ponieważ zasób jest nabywany, gdy obiekt kontrolujący zasób jest konstruowany, jeśli konstruktor nie powiódł się (tj. z powodu wyjątku) zasób nie jest nabywany. Następnie gdy obiekt wyjdzie poza zakres zasób jest zwolniony. c++ gwarantuje, że wszystkie obiekty na stosie, które zostały pomyślnie skonstruowane, zostaną zniszczone(dotyczy to konstruktorów klas bazowych i elementów składowych, nawet jeśli konstruktor klasy super zawiedzie).

Rational stojący za RAII polega na tym, aby wyjątek dotyczący pozyskiwania zasobów był bezpieczny. Że wszystkie pozyskane zasoby są odpowiednio uwalniane bez względu na to, gdzie występuje wyjątek. Zależy to jednak od jakości klasy, która nabywa zasób (musi to być bezpieczne dla wyjątków i jest to hard).

 8
Author: iain,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-03 07:45:31

Chciałbym ująć to nieco mocniej niż poprzednie odpowiedzi.

RAII, pozyskiwanie zasobów jest inicjalizacją oznacza, że wszystkie pozyskane zasoby powinny być pozyskiwane w kontekście inicjalizacji obiektu. Zabrania to" nagiego " pozyskiwania zasobów. Uzasadnieniem jest to, że cleanup w C++ działa na zasadzie obiektowej, a nie wywołania funkcji. Dlatego wszystkie sprzątanie powinno być wykonywane przez obiekty, a nie wywołania funkcji. W tym sensie C++ jest bardziej zorientowany obiektowo niż np. Java. Java czyszczenie jest oparte na wywołaniach funkcji w klauzulach finally.

 8
Author: MSalters,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-22 12:29:11

Problem ze śmieciami polega na tym, że tracisz deterministyczną destrukcję, która jest kluczowa dla RAII. Gdy zmienna wyjdzie poza zakres, to od garbage collector zależy, kiedy obiekt zostanie odzyskany. Surowiec przechowywany przez obiekt będzie przechowywany do czasu wywołania destruktora.

 7
Author: Mark Ransom,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-03 05:34:56

RAII pochodzi z inicjalizacji alokacji zasobów. Zasadniczo oznacza to, że gdy konstruktor zakończy wykonywanie, skonstruowany obiekt jest w pełni zainicjalizowany i gotowy do użycia. Oznacza to również, że Destruktor uwolni wszelkie zasoby (np. pamięć, zasoby systemu operacyjnego) należące do obiektu.

W porównaniu ze śmieciowymi językami/technologiami (np. Java,. Net), C++ pozwala na pełną kontrolę nad życiem obiektu. Dla obiektu przydzielonego stosem, dowiesz się, kiedy zostanie wywołany Destruktor obiektu (gdy wykonanie wyjdzie poza zakres), rzecz, która nie jest tak naprawdę kontrolowana w przypadku zbierania śmieci. Nawet używając inteligentnych wskaźników w C++ (np. boost::shared_ptr), będziesz wiedział, że gdy nie ma odniesienia do wskazanego obiektu, zostanie wywołany Destruktor tego obiektu.

 4
Author: Cătălin Pitiș,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-03 06:08:25

I jak możesz zrobić coś na stosie, co spowoduje oczyszczenie czegoś, co żyje na stercie?

class int_buffer
{
   size_t m_size;
   int *  m_buf;

   public:
   int_buffer( size_t size )
     : m_size( size ), m_buf( 0 )
   {
       if( m_size > 0 )
           m_buf = new int[m_size]; // will throw on failure by default
   }
   ~int_buffer()
   {
       delete[] m_buf;
   }
   /* ...rest of class implementation...*/

};


void foo() 
{
    int_buffer ib(20); // creates a buffer of 20 bytes
    std::cout << ib.size() << std::endl;
} // here the destructor is called automatically even if an exception is thrown and the memory ib held is freed.

Gdy instancja int_buffer powstanie, musi mieć rozmiar i przydziela niezbędną pamięć. Kiedy wychodzi poza zasięg, nazywa się go destruktorem. Jest to bardzo przydatne w przypadku obiektów synchronizacji. Consider

class mutex
{
   // ...
   take();
   release();

   class mutex::sentry
   {
      mutex & mm;
      public:
      sentry( mutex & m ) : mm(m) 
      {
          mm.take();
      }
      ~sentry()
      {
          mm.release();
      }
   }; // mutex::sentry;
};
mutex m;

int getSomeValue()
{
    mutex::sentry ms( m ); // blocks here until the mutex is taken
    return 0;  
} // the mutex is released in the destructor call here.
Są też przypadki, w których nie możesz użyć RAII?
Nie, Nie naprawdę.

Czy kiedykolwiek marzyłeś o zbieraniu śmieci? Co najmniej garbage collector można użyć dla niektórych obiektów, pozwalając innym być zarządzane?

Nigdy. Usuwanie śmieci rozwiązuje tylko bardzo mały podzbiór dynamicznego zarządzania zasobami.
 3
Author: Rob K,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-26 20:16:39

Jest tu już wiele dobrych odpowiedzi, ale chciałbym tylko dodać:
Prostym wyjaśnieniem RAII jest to, że w C++ Obiekt przydzielony na stos jest niszczony za każdym razem, gdy wychodzi poza zakres. Oznacza to, że zostanie wywołany Destruktor obiektów i może wykonać wszystkie niezbędne czyszczenie.
Oznacza to, że jeśli obiekt jest tworzony bez "new", nie jest wymagane "delete". I to jest również idea "inteligentnych wskaźników" - znajdują się one na stosie i zasadniczo owija obiekt oparty na stercie.

 2
Author: E Dominique,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-03 11:04:53

RAII to skrót od Resource Acquisition Is Initialization.

Ta technika jest bardzo unikalna dla C++ ze względu na ich wsparcie zarówno dla konstruktorów i destruktorów , jak i prawie automatycznie konstruktorów, które pasują do przekazywanych argumentów lub w najgorszym przypadku domyślny konstruktor jest nazywany & destruktorami, jeśli explicity jest wywoływany, w przeciwnym razie domyślny konstruktor, który jest dodawany przez kompilator C++, jest wywoływany, jeśli nie napisałeś destruktora jawnie dla C++. klasy. Dzieje się tak tylko w przypadku obiektów C++, które są automatycznie zarządzane - co oznacza, że nie używają wolnego magazynu (pamięć alokowana / dealokowana za pomocą operatorów new, new [] / delete,delete [] C++).

Technika RAII wykorzystuje tę funkcję auto-managed object do obsługi obiektów utworzonych na stercie / free-store poprzez explicitly prosząc o więcej pamięci używając new / new [], które powinny być jawnie zniszczone przez wywołanie delete / delete[]. Automatycznie zarządzana Klasa obiektu zawija tę inną obiekt, który zostanie utworzony w pamięci sterty/free-store. Stąd, gdy konstruktor automatycznie zarządzanego obiektu jest uruchomiony, zawinięty obiekt jest tworzony na stercie / pamięci wolnego magazynu , a gdy automatycznie zarządzany uchwyt obiektu wychodzi poza zakres, automatycznie wywoływany jest Destruktor tego automatycznie zarządzanego obiektu, w którym zawinięty obiekt jest niszczony za pomocą delete. W przypadku pojęć OOP, jeśli zawijasz takie obiekty wewnątrz innej klasy w zakresie prywatnym, nie masz dostępu do owiniętych klas członków i metod & to jest powód, dla którego są przeznaczone Inteligentne Wskaźniki (aka klasy obsługi). Te inteligentne wskaźniki ujawniają zawinięty obiekt jako typowany obiekt do zewnętrznego świata i tam, umożliwiając wywołanie dowolnych elementów / metod, z których składa się obiekt pamięci. Zauważ, że inteligentne wskaźniki mają różne smaki w zależności od różnych potrzeb. Powinieneś odnieść się do nowoczesnego programowania C++ Andrei Alexandrescu lub boost library (www.boostorg) shared_ptr.wdrożenie/dokumentacja hpp, aby dowiedzieć się więcej na ten temat. Nadzieja to pomaga Ci zrozumieć RAII.

 1
Author: techcraver,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-03 10:03:25