Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Un unique_ptr no comparte su puntero. No se puede copiar en otro unique_ptr, transferirse por valor a una función ni utilizarse en ningún algoritmo de la biblioteca estándar de C++ que requiera la creación de copias. Un unique_ptr solo se puede mover. Esto significa que la propiedad del recurso de memoria se transfiere a otro unique_ptr y el unique_ptr original deja de poseerlo. Se recomienda restringir un objeto a un propietario, ya que la propiedad múltiple agrega complejidad. Cuando necesite un puntero inteligente para un objeto C++ simple, use unique_ptr, y cuando cree un unique_ptr, use la función auxiliar make_unique.
El diagrama siguiente muestra la transferencia de propiedad entre dos instancias de unique_ptr.
unique_ptr se define en el encabezado <memory> de la Biblioteca estándar de C++. Es exactamente tan eficaz como un puntero sin procesar y se puede usar en contenedores de la biblioteca estándar de C++. La adición de instancias de unique_ptr a los contenedores de la Biblioteca Estándar de C++ es eficiente porque el constructor de movimiento de unique_ptr elimina la necesidad de una operación de copia.
Para usar unique_ptr y make_unique, incluya el <memory> encabezado . En los ejemplos siguientes se compilan y se ejecutan como programas independientes.
Ejemplo 1
En el ejemplo siguiente se muestra cómo crear instancias de unique_ptr y pasarlas entre funciones. Al devolver un unique_ptr por valor, se transfiere la propiedad al autor de la llamada. Al pasar un unique_ptr por valor a una función, se transfiere la propiedad al destinatario.
// Compile with: cl /EHsc /std:c++17
#include <iostream>
#include <memory>
#include <string>
struct Song {
std::string artist;
std::string title;
Song(const std::string& a, const std::string& t) : artist(a), title(t) {
std::cout << "Created: " << title << "\n";
}
~Song() { std::cout << "Destroyed: " << title << "\n"; }
};
// Returning a unique_ptr by value transfers ownership to the caller.
std::unique_ptr<Song> SongFactory(const std::string& artist, const std::string& title) {
return std::make_unique<Song>(artist, title);
}
// Passing a unique_ptr by value transfers ownership to the function.
// The Song is automatically destroyed when the function exits.
void SingSong(std::unique_ptr<Song> song) {
std::cout << "Singing: " << song->title << " by " << song->artist << "\n";
}
int main() {
// Create a new unique_ptr with a new object.
auto song = std::make_unique<Song>("Mr. Children", "Namonaki Uta");
std::cout << "song points to: " << song->title << "\n";
// Move ownership from one unique_ptr to another.
std::unique_ptr<Song> song2 = std::move(song);
std::cout << "After move, song is " << (song ? "not null" : "null") << "\n";
std::cout << "song2 points to: " << song2->title << "\n";
// Obtain unique_ptr from a factory function that returns by value.
auto song3 = SongFactory("Michael Jackson", "Beat It");
// Transfer ownership to a function.
SingSong(std::move(song3));
std::cout << "After SingSong, song3 is " << (song3 ? "not null" : "null") << "\n";
}
Created: Namonaki Uta
song points to: Namonaki Uta
After move, song is null
song2 points to: Namonaki Uta
Created: Beat It
Singing: Beat It by Michael Jackson
Destroyed: Beat It
After SingSong, song3 is null
Destroyed: Namonaki Uta
Estos ejemplos muestran esta característica básica de unique_ptr: se puede mover, pero no copiar. "Mover" transfiere la propiedad a un nuevo unique_ptr y restablece el antiguo unique_ptr.
Ejemplo 2
En el ejemplo siguiente se muestra cómo crear instancias del objeto unique_ptr y usarlas en un vector.
// Compile with: cl /EHsc /std:c++17
#include <iostream>
#include <memory>
#include <string>
#include <vector>
struct Song {
std::string artist;
std::string title;
Song(const std::string& a, const std::string& t) : artist(a), title(t) {}
};
int main() {
std::vector<std::unique_ptr<Song>> songs;
// Create unique_ptr<Song> instances and add them to the vector
// using implicit move semantics.
songs.push_back(std::make_unique<Song>("B'z", "Juice"));
songs.push_back(std::make_unique<Song>("Namie Amuro", "Funky Town"));
songs.push_back(std::make_unique<Song>("Kome Kome Club", "Kimi ga Iru Dake de"));
songs.push_back(std::make_unique<Song>("Ayumi Hamasaki", "Poker Face"));
// Pass by const reference to avoid copying.
// Passing by value causes a compile error because
// the unique_ptr copy constructor is deleted.
for (const auto& song : songs) {
std::cout << "Artist: " << song->artist
<< " Title: " << song->title << "\n";
}
// The unique_ptr instances in the vector are automatically destroyed when the vector goes out of scope at the end of main()
}
Artist: B'z Title: Juice
Artist: Namie Amuro Title: Funky Town
Artist: Kome Kome Club Title: Kimi ga Iru Dake de
Artist: Ayumi Hamasaki Title: Poker Face
Destroyed: Juice
Destroyed: Funky Town
Destroyed: Kimi ga Iru Dake de
Destroyed: Poker Face
En el intervalo del bucle, observe que unique_ptr se pasa por referencia. Si intenta pasar el parámetro por valor aquí, el compilador notificará un error porque se elimina el constructor de copias unique_ptr.
Ejemplo 3
En el siguiente ejemplo se muestra cómo se inicializa un unique_ptr que es miembro de una clase.
// Compile with: cl /EHsc /std:c++17
#include <iostream>
#include <memory>
class Engine {
public:
Engine() { std::cout << "Engine created\n"; }
~Engine() { std::cout << "Engine destroyed\n"; }
void Run() { std::cout << "Engine running\n"; }
};
class Car {
private:
// Car owns the unique_ptr.
std::unique_ptr<Engine> engine;
public:
// Initialize by using make_unique in the member initializer list.
Car() : engine(std::make_unique<Engine>()) {}
void Start() {
engine->Run();
}
};
int main() {
Car car;
car.Start();
}
Engine created
Engine running
Engine destroyed
Ejemplo 4
Puede usar make_unique para crear un unique_ptr a un array.
make_unique<int[]>(5) crea una matriz de cinco elementos que se inicializa en cero. No puede pasar valores de elemento individuales a make_unique, por lo que asígnelos después de la creación.
// Compile with: cl /EHsc /std:c++17
#include <iostream>
#include <memory>
int main() {
// Create a unique_ptr to an array of 5 integers.
// The elements are value-initialized to 0.
auto p = std::make_unique<int[]>(5);
// Assign values to the array elements.
for (int i = 0; i < 5; ++i) {
p[i] = i;
std::cout << p[i] << "\n";
}
// The array is automatically deleted when p goes out of scope.
}
0
1
2
3
4
Para obtener más ejemplos, consulte make_unique.