Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?
Opracował: Piotr DejaVu Szawdyński
Język C++

shared_ptr

[szablon klasy] Przechowuje wskaźnik i kontroluje liczbę istniejących kopii wskaźnika (automatycznie zwalnia pamięć).

Składnia

C/C++
#include <memory>

namespace std
{
    template < class T >
    class shared_ptr
    {
        //...
    };
}

Opis szczegółowy

Szablon klasy, którego zadaniem jest zliczanie liczby referencji dla dynamicznie zaalokowanego obiektu. Zaalokowany obiekt jest natychmiast zwalniany z chwilą, gdy licznik referencji osiągnie wartość zero, tj. gdy ostatnia istniejąca referencja zostanie zniszczona.

Szablon klasy std::shared_ptr gwarantuje, że liczba referencji będzie zawsze prawidłowa, zarówno w aplikacjach sekwencyjnych, jak również w aplikacjach wielowątkowych. Dzięki temu programista ma gwarancję, że obiekt trzymany za pomocą std::shared_ptr zostanie zawsze poprawnie zwolniony.

Czy wiesz, że?

Szablon klasy std::shared_ptr prawidłowo zlicza referencje w aplikacjach wielowątkowych.

Przykłady

Prosty przykład użycia std::shared_ptr

C/C++
#include <memory>
#include <cstdio>

int main()
{
    typedef std::shared_ptr < int > REF_Int;
    REF_Int refLiczba1;
    {
        REF_Int refLiczba2( new int( 123 ) );
        printf( "Liczba referencji (refLiczba1) = %d\n", refLiczba1.use_count() );
        printf( "Liczba referencji (refLiczba2) = %d\n", refLiczba2.use_count() );
        refLiczba1 = refLiczba2;
        printf( "Wartosc (refLiczba2) = %d\n", * refLiczba2 );
        * refLiczba2 = 456;
        printf( "refLiczba1 = refLiczba2;\n" );
        printf( "Liczba referencji (refLiczba1) = %d\n", refLiczba1.use_count() );
        printf( "Liczba referencji (refLiczba2) = %d\n", refLiczba2.use_count() );
        printf( "Wychodze ze scope-a...\n" );
    }
    printf( "Liczba referencji (refLiczba1) = %d\n", refLiczba1.use_count() );
    printf( "Wartosc (refLiczba1) = %d\n", * refLiczba1 );
    return 0;
}
Standardowe wyjście programu:
Liczba referencji (refLiczba1) = 0
Liczba referencji (refLiczba2) = 1
Wartosc (refLiczba2) = 123
refLiczba1 = refLiczba2;
Liczba referencji (refLiczba1) = 2
Liczba referencji (refLiczba2) = 2
Wychodze ze scope-a...
Liczba referencji (refLiczba1) = 1
Wartosc (refLiczba1) = 456

Zliczanie referencji w aplikacji wielowątkowej

Poniższy kod prezentuje poprawne działanie zliczania referencji dla wskaźnika typu std::shared_ptr w aplikacji wielowątkowej.
C/C++
#include <memory>
#include <thread>
#include <cstdio>
#include <vector>
#include <sstream>

class CObiekt
{
public:
    CObiekt()
        : m_iCounter( 0 )
    {
        printf( "Konstruktor\n" );
    }
   
    void inc()
    {
        ++m_iCounter; //INFO: ten kod nie jest bezpieczny dla aplikacji wielowątkowej (ale to nie jest istotne w rozpatrywanym problemie)
    }
   
    virtual ~CObiekt()
    {
        printf( "Destruktor (%d)\n", m_iCounter );
    }
private:
    int m_iCounter;
}; //class CObiekt

typedef std::shared_ptr < CObiekt > REF_Obiekt;

void zonglowanieSharedPtr( std::shared_ptr < CObiekt >& refObiekt )
{
    std::stringstream sThreadName;
    sThreadName << std::this_thread::get_id();
    printf( "[ID = %s] Thread created!\n", sThreadName.str().c_str() );
    for( int i = 0; i < 10000; ++i )
    {
        REF_Obiekt obiekt = refObiekt;
        obiekt->inc();
    } //for
    printf( "[ID = %s] Closing thread!\n", sThreadName.str().c_str() );
}

int main()
{
    REF_Obiekt ref_value( new CObiekt() );
    std::vector < std::thread > vThreads;
    for( int i = 0; i < 10; ++i )
    {
        vThreads.push_back( std::thread( zonglowanieSharedPtr, ref_value ) );
        printf( "Liczba referencji = %d\n", ref_value.use_count() );
    } //for
   
    zonglowanieSharedPtr( ref_value );
    for( auto & item: vThreads )
         item.join();
   
    printf( "Liczba referencji = %d ( wartosc 1 oznacza poprawna liczbe referencji )\n", ref_value.use_count() );
    return 0;
}
Możliwe standardowe wyjście programu:
Konstruktor
Liczba referencji = 2
[ID = 7028] Thread created!
[ID = 7028] Closing thread!
[ID = 7032] Thread created!
[ID = 7032] Closing thread!
Liczba referencji = 2
Liczba referencji = 2
[ID = 7036] Thread created!
Liczba referencji = 3
Liczba referencji = 5
[ID = 7036] Closing thread!
Liczba referencji = 4
[ID = 7040] Thread created!
[ID = 7048] Thread created!
[ID = 7044] Thread created!
[ID = 7040] Closing thread!
[ID = 7044] Closing thread!
[ID = 7048] Closing thread!
Liczba referencji = 5
[ID = 7052] Thread created!
Liczba referencji = 3
Liczba referencji = 4
[ID = 7052] Closing thread!
[ID = 7060] Thread created!
[ID = 7064] Thread created!
[ID = 7056] Thread created!
[ID = 7060] Closing thread!
Liczba referencji = 5
[ID = 7016] Thread created!
[ID = 7064] Closing thread!
[ID = 7056] Closing thread!
[ID = 7016] Closing thread!
Liczba referencji = 1 ( wartosc 1 oznacza poprawna liczbe referencji )
Destruktor (97263)

Linki zewnętrzne