c++ - shared_ptr - ¿Qué sucede con unique_ptr después de std:: move()?




unique_ptr example (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 de u 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.





unique-ptr