Compartilhar via


Como: criar e usar instâncias shared_ptr

O tipo de shared_ptr é um ponteiro inteligente na biblioteca padrão C++ que é criada para cenários em que mais de um proprietário pode ter que gerenciar o tempo de vida do objeto na memória.Depois que você inicializa shared_ptr que você pode copiar o, passá-lo pelo valor em argumentos de função, e o atribui a outras instâncias de shared_ptr .Qualquer ponto das instâncias para a mesma objetos, e compartilhar o acesso a um bloco de “controle” que realiza e diminuições que a contagem de referência sempre que shared_ptr novo é adicionado, sai do escopo, ou é redefinido.Quando a contagem de referência atinge zero, o bloco de controle exclui o recurso e próprio de memória.

A ilustração a seguir mostra várias instâncias de shared_ptr apontando para um local da memória.

Ponteiro compartilhado

Exemplo

Sempre que possível, use a função de make_shared (<memory>) para criar shared_ptr quando o recurso de memória é criado pela primeira vez.make_shared seguro. é exceçãoUsa o mesmo chamada para alocar memória para o bloco de controle e o recurso, e assim reduzir a sobrecarga de compilação.Se você não usar make_shared, então você precisa usar uma nova expressão explícita para criar o objeto antes que você passe o para o construtor de shared_ptr .O exemplo a seguir mostra várias maneiras para declarar e inicializar shared_ptr juntamente com um novo objeto.


// Use make_shared function when possible.
auto sp1 = make_shared<Song>(L"The Beatles", L"Im Happy Just to Dance With You");

// Ok, but slightly less efficient. 
// Note: Using new expression as constructor argument
// creates no named variable for other code to access.
shared_ptr<Song> sp2(new Song(L"Lady Gaga", L"Just Dance"));

// When initialization must be separate from declaration, e.g. class members, 
// initialize with nullptr to make your programming intent explicit.
shared_ptr<Song> sp5(nullptr);
//Equivalent to: shared_ptr<Song> sp5;
//...
sp5 = make_shared<Song>(L"Elton John", L"I'm Still Standing");

O exemplo a seguir mostra como declarar e inicializar as instâncias de shared_ptr que levam a propriedade compartilhado de um objeto que é atribuído já por outro shared_ptr.Suponha que sp2 é shared_ptrinicializado.

//Initialize with copy constructor. Increments ref count.
auto sp3(sp2);

//Initialize via assignment. Increments ref count.
auto sp4 = sp2;

//Initialize with nullptr. sp7 is empty.
shared_ptr<Song> sp7(nullptr);

// Initialize with another shared_ptr. sp1 and sp2
// swap pointers as well as ref counts.
sp1.swap(sp2);

shared_ptr também é útil em um contêiner padrão de (STL) biblioteca de modelo quando você estiver usando os algoritmos que copia os elementos.Você pode envolver os elementos em shared_ptr, e copie em outros contêineres com um entendimento que a memória subjacente é válido como precisar, e não.O exemplo a seguir mostra como usar o algoritmo de replace_copy_if em instâncias de shared_ptr em um vetor.

vector<shared_ptr<Song>> v;

v.push_back(make_shared<Song>(L"Bob Dylan", L"The Times They Are A Changing"));
v.push_back(make_shared<Song>(L"Aretha Franklin", L"Bridge Over Troubled Water"));
v.push_back(make_shared<Song>(L"Thal�a", L"Entre El Mar y Una Estrella"));

vector<shared_ptr<Song>> v2;
remove_copy_if(v.begin(), v.end(), back_inserter(v2), [] (shared_ptr<Song> s) 
{
    return s->artist.compare(L"Bob Dylan") == 0;     
});


for_each(v2.begin(), v2.end(), [] (shared_ptr<Song> s)
{
    wcout << s->artist << L":" << s->title << endl;
});

Você pode usar dynamic_pointer_cast, static_pointer_cast, e const_pointer_cast para converter shared_ptr.Essas funções são semelhantes a dynamic_cast, a static_cast, e a operadores de const_cast .O exemplo a seguir mostra como testar o tipo derivado de cada elemento em um vetor de shared_ptr de classes base, e então copiar os elementos e informações de exibição neles.

    vector<shared_ptr<MediaAsset>> assets;

    assets.push_back(shared_ptr<Song>(new Song(L"Himesh Reshammiya", L"Tera Surroor")));
    assets.push_back(shared_ptr<Song>(new Song(L"Penaz Masani", L"Tu Dil De De")));
    assets.push_back(shared_ptr<Photo>(new Photo(L"2011-04-06", L"Redmond, WA", L"Soccer field at Microsoft.")));

    vector<shared_ptr<MediaAsset>> photos;

    copy_if(assets.begin(), assets.end(), back_inserter(photos), [] (shared_ptr<MediaAsset> p) -> bool
    {
        // Use dynamic_pointer_cast to test whether
        // element is a shared_ptr<Photo>.
        shared_ptr<Photo> temp = dynamic_pointer_cast<Photo>(p);        
        return temp.get() != nullptr;
    });

    for_each(photos.begin(), photos.end(), [] (shared_ptr<MediaAsset> p)
    {
        // We know that the photos vector contains only 
        // shared_ptr<Photo> objects, so use static_cast.
        wcout << "Photo location: " << (static_pointer_cast<Photo>(p))->location_ << endl;
    });

Você pode passar shared_ptr a outra função das seguintes maneiras:

  • Passar shared_ptr por valor.Isso chama o construtor de impressão, incrementa contagem de referência, e faz o receptor um proprietário.Há uma pequena quantidade de sobrecarga nesta operação, que pode ser significativa segundo quantos objetos de shared_ptr você está passando.Use esta opção quando o contrato de código (implicado ou explícito) entre o chamador e o receptor requer que o receptor é um proprietário.

  • Passagem por referência shared_ptr ou referência const.Nesse caso, a contagem de referência não é incrementada, e o receptor pode acessar o ponteiro como o chamador não sai do escopo.Ou, o receptor pode decidir criar shared_ptr baseado na referência, e inferior dessa maneira semelhante em um proprietário compartilhado.Use esta opção quando o chamador não tem nenhum conhecimento de receptor, ou quando você deve passar shared_ptr e o desejar evitar a operação de cópia por razões de desempenho.

  • Passar o ponteiro subjacente ou uma referência ao objeto subjacente.Isso permite que o receptor para usar o objeto, mas não permite que você compartilhe a propriedade ou estender o tempo de vida.Se o receptor cria shared_ptr ponteiro " bruto ", nova shared_ptr é independente de original, e não controla o recurso subjacente.Use esta opção quando o contrato entre o chamador e o receptor claramente especifica que o chamador mantém a propriedade do tempo de vida de shared_ptr .

  • Quando você decidir como passar shared_ptr, determina se o receptor precisa compartilhar a propriedade de recurso subjacente.Um “dono” é um objeto ou funções que pode manter o recurso subjacente ativa desde que o precisa.Se o chamador tiver que garantir que o receptor pode estender a vida útil do ponteiro além do (tempo de vida da função), use a primeira opção.Se você não importa se o receptor se estende o tempo de vida, então a passagem por referência e à esquerda do receptor copie ou não.

  • Se você precisa dar a um auxiliar acesso ao ponteiro de função subjacente, e você souber que a função auxiliar apenas usará o ponteiro e retornará antes que a função de chamada retornar, então a função não precisa compartilhar a propriedade do ponteiro subjacente.Apenas precise acessar o ponteiro do tempo de vida de shared_ptrdo chamador.Nesse caso, é seguro shared_ptr passar por referência, ou passar o ponteiro " bruto " ou uma referência ao objeto subjacente.Passar essa maneira fornece um benefício pequeno de desempenho, e também podem ajudá-lo a expressar sua intenção de programação.

  • Às vezes, por exemplo em std:vector<shared_ptr<T>>, você pode ter que passar cada shared_ptr a um corpo da expressão lambda ou a um objeto chamado de função.Se o método ou função não estiver armazenando o ponteiro, então passar shared_ptr em função de evitam chamar o construtor de impressão para cada elemento.

O exemplo a seguir mostra como shared_ptr sobrecarga vários operadores de comparação para ativar comparações do ponteiro na memória que é pertencente a instâncias de shared_ptr .


// Initialize two separate raw pointers.
// Note that they contain the same values.
auto song1 = new Song(L"Village People", L"YMCA");
auto song2 = new Song(L"Village People", L"YMCA");

// Create two unrelated shared_ptrs.
shared_ptr<Song> p1(song1);    
shared_ptr<Song> p2(song2);

// Unrelated shared_ptrs are never equal.
wcout << "p1 < p2 = " << std::boolalpha << (p1 < p2) << endl;
wcout << "p1 == p2 = " << std::boolalpha <<(p1 == p2) << endl;

// Related shared_ptr instances are always equal.
shared_ptr<Song> p3(p2);
wcout << "p3 == p2 = " << std::boolalpha << (p3 == p2) << endl; 

Consulte também

Conceitos

Ponteiros inteligentes (guia de programação do C++ moderno)