Compartir a través de


Cómo: Cree y use las instancias shared_ptr

El tipo de shared_ptr es puntero inteligente en la biblioteca estándar de C++ que está diseñado para escenarios en los que más de un propietario tendrá que administrar la duración del objeto en memoria.Después de inicializar shared_ptr que puede copiarlo, pase por valor de argumentos de función, y asígnelo a otras instancias de shared_ptr.Todo el punto de instancias al mismo objeto, y el acceso de la acción a “bloque de control” que incrementa y decrementa siempre que se agregue un nuevo shared_ptr, salga del ámbito, o se restablece.Cuando el recuento de referencias llega a cero, el bloque de control elimina el recurso de memoria y propio.

La ilustración siguiente muestra varias instancias de shared_ptr que apuntan a una ubicación de memoria.

Puntero compartido

Ejemplo

Siempre que sea posible, utilice la función de make_shared (<memory>) para crear shared_ptr cuando se crea el recurso de memoria por primera vez.make_shared es excepción-seguro.Utiliza la misma llamada para asignar memoria para el bloque de control y el recurso, y por tanto reduce la sobrecarga de la construcción.Si no utiliza make_shared, se tiene que utilizar una nueva expresión explícita para crear el objeto antes de que se pasa al constructor de shared_ptr.El ejemplo siguiente se muestran varias maneras de declarar e inicializar shared_ptr junto con un nuevo 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");

El ejemplo siguiente se muestra cómo declarar e inicializar las instancias de shared_ptr que adquieren propiedad compartida de un objeto que se ha asignado ya por otro shared_ptr.Suponga que sp2 es shared_ptr inicializado.

//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 también es útil en contenedores estándar de (STL) de la plantilla cuando utiliza los algoritmos que copian elementos.Puede ajustar elementos en shared_ptr, y lo copia en otros contenedores entendiendo que la memoria subyacente es válida mientras lo necesite, y no más.El ejemplo siguiente se muestra cómo usar el algoritmo de replace_copy_if en instancias de shared_ptr en un vector.

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;
});

Puede utilizar dynamic_pointer_cast, static_pointer_cast, y const_pointer_cast para convertir shared_ptr.Estas funciones se parecen a dynamic_cast, a static_cast, y operadores de const_cast.El ejemplo siguiente se muestra cómo probar el tipo derivado de cada elemento del vector de shared_ptr de clases base, y copie los elementos y mostrar información sobre ellos.

    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;
    });

Puede pasar shared_ptr a otra función de las maneras siguientes:

  • Pase shared_ptr por valor.Esto invoca el constructor de copias, incrementa el recuento de referencias, y crea el destinatario un propietario.Hay una pequeña cantidad de sobrecarga de esta operación, que puede ser significativa en función del número de objetos de shared_ptr está pasando.Utilice esta opción cuando el contrato de código (implicada o explícito) entre el llamador y el destinatario requiere que el destinatario es propietario.

  • Pase shared_ptr por referencia o referencia const.En este caso, el recuento de referencias no se incrementa, y el destinatario puede tener acceso al puntero al llamador no salga del ámbito.O, el destinatario puede decidir crear shared_ptr basado en la referencia, y por tanto hacer propietario compartido.Utilice esta opción cuando el llamador no tiene conocimiento de destinatarios, o cuando se debe pasar shared_ptr y desea evitar la operación de copia por razones de rendimiento.

  • Pase el puntero subyacente o una referencia al objeto subyacente.Esto permite al destinatario para utilizar el objeto, pero no permite compartir propiedad o para extender la duración.Si el destinatario crea shared_ptr de puntero sin formato, nuevo shared_ptr es independiente del original, y no controla el recurso subyacente.Utilice esta opción cuando el contrato entre el llamador y el destinatario especifica claramente que el llamador conserva la propiedad de la duración de shared_ptr.

  • Cuando se decidir cómo pasar shared_ptr, determina si el destinatario tiene que compartir la propiedad del recurso subyacente.Un “propietario” es un objeto o funciona para el cual puede mantener el recurso subyacente activo mientras lo necesite.Si el llamador tiene que garantizar que el destinatario puede extender la vida del puntero más allá de la duración (de función), utilice la primera opción.Si no utiliza si extiende el destinatario la duración, el paso por referencia y permitir que el destinatario copiarla o no.

  • Si tiene que proporcionar a una aplicación auxiliar el acceso de la función a puntero subyacente, y sabe que la función auxiliar solo utilizará el puntero y volverá antes de que la función de llamada vuelve, después de que la función no tiene que compartir la propiedad del puntero subyacente.Solo debe tener acceso al puntero dentro de la duración de shared_ptr del llamador.En este caso, es segura shared_ptr por referencia, o pase el puntero sin formato o una referencia al objeto subyacente.Pasar esta manera proporciona una pequeña ventaja de rendimiento, y también puede ayudarle a expresar la intención de la programación.

  • A veces, por ejemplo en std:vector<shared_ptr<T>>, puede que tenga que pasar cada shared_ptr un cuerpo de la expresión lambda o un objeto con nombre de la función.Si la expresión lambda o función no está almacenando el puntero, debe pasar shared_ptr en referencia a evitar llamar al constructor de copias para cada elemento.

El ejemplo siguiente se muestra cómo shared_ptr sobrecarga distintos operadores de comparación para habilitar comparaciones de punteros en memoria que pertenece a las instancias 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; 

Vea también

Conceptos

Punteros inteligentes (C++ moderno)