c++ - make_unique - shared_ptr
¿Qué sucede con unique_ptr después de std:: move()? (2)
El estándar dice (§ 20.8.1.2.1 ¶ 16, énfasis agregado) que el constructor de movimiento de std::unique_ptr
unique_ptr(unique_ptr&& u) noexcept;
Construye un
unique_ptr
transfiriendo la propiedad deu
a*this
.
Por lo tanto, después de mover-construir el objeto temporal que se pasa como argumento a attachActor
su tony
, tony
ya no es el propietario del objeto y, por tony.get() == nullptr
tanto, tony.get() == nullptr
. (Este es uno de los pocos casos en que la biblioteca estándar en realidad hace afirmaciones sobre el estado de un objeto alejado).
Sin embargo, el deseo de devolver la referencia se puede cumplir sin recurrir a punteros new
y sin procesar.
Tony&
Movie::addTony()
{
auto tony = std::make_unique<Tony>();
auto p = tony.get();
attachActor(std::move(tony));
return *p;
}
Este código asume que attachActor
no dejará caer su argumento en el piso. De lo contrario, el puntero p
attachActor
después de que attachActor
haya return
ed. Si no se puede confiar en esto, tendrá que rediseñar su interfaz y usar punteros compartidos en su lugar.
std::shared_ptr<Tony>
Movie::addTony()
{
auto tony = std::make_shared<Tony>();
attachActor(tony);
return tony;
}
Este código es lo que quiero hacer:
Tony& Movie::addTony()
{
Tony *newTony = new Tony;
std::unique_ptr<Tony> tony(newTony);
attachActor(std::move(tony));
return *newTony;
}
Me pregunto si podría hacer esto en su lugar:
Tony& Movie::addTony()
{
std::unique_ptr<Tony> tony(new Tony);
attachActor(std::move(tony));
return *tony.get();
}
¿Pero será *tony.get()
el mismo puntero o nulo? Sé que podría verificarlo, pero ¿qué es lo estándar que debe hacer?
No, no puedes hacer eso en su lugar. Mover el unique_ptr
lo unique_ptr
. Si no fuera así, entonces no sería único. Por supuesto, estoy asumiendo que attachActor
no hace algo tonto como esto:
attachActor(std::unique_ptr<Tony>&&) {
// take the unique_ptr by r-value reference,
// and then don''t move from it, leaving the
// original intact
}
Sección 20.8.1 párrafo 4.
Además, u (el objeto unique_ptr) puede, previa solicitud, transferir la propiedad a otro puntero único u2. Al término de dicha transferencia, se mantienen las siguientes condiciones posteriores:
- u2.p es igual a la transferencia previa hacia arriba,
- arriba es igual a nullptr , y
- si el estado ud previo a la transferencia se mantuvo, dicho estado se ha transferido a u2.d.