¿Por qué el RPP único toma dos parámetros de plantilla cuando el rpp compartido solo toma uno?


Ambos unique_ptr y shared_ptr acepte un destructor personalizado para llamar al objeto que posee. Pero en el caso de unique_ptr, el destructor se pasa como un parámetro de plantilla de la clase , mientras que el tipo de destructor personalizado de shared_ptr debe especificarse como un parámetro de plantilla del constructor .

template <class T, class D = default_delete<T>> 
class unique_ptr
{
    unique_ptr(T*, D&); //simplified
    ...
};

Y

template<class T>
class shared_ptr
{
    template<typename D>
    shared_ptr(T*, D); //simplified
    ...
};

No puedo ver por qué tal diferencia. ¿Qué requiere eso?

Author: user703016, 2014-01-25

2 answers

Si proporciona el deleter como argumento de plantilla (como en unique_ptr) es parte del tipo y no necesita almacenar nada adicional en los objetos de este tipo. Si deleter se pasa como argumento del constructor (como en shared_ptr) necesita almacenarlo en el objeto. Este es el costo de la flexibilidad adicional, ya que puede usar diferentes deleters para los objetos del mismo tipo.

Supongo que esta es la razón: unique_ptr se supone que es un objeto muy ligero con cero sobrecarga. Almacenar los deleters con cada unique_ptr podrían duplicar su tamaño. Debido a eso, la gente usaría buenos punteros crudos en su lugar, lo que estaría mal.

Por otro lado, shared_ptr no es tan liviano, ya que necesita almacenar el recuento de referencias, por lo que almacenar un deleter personalizado también parece un buen intercambio.

 54
Author: Wojtek Surowka,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-15 21:10:55

Los punteros compartidos de diferentes tipospueden compartir la propiedad del mismo objeto. Véase sobrecarga (8) de std::shared_ptr::shared_ptr. Los punteros únicos no necesitan tal mecanismo, ya que no comparten.

template< class Y > 
shared_ptr( const shared_ptr<Y>& r, element_type* ptr ) noexcept;

Si no escribiera-borre el deleter, no sería capaz de usar un shared_ptr<T, Y_Deleter> como un shared_ptr<T>, lo que lo haría básicamente inútil.

¿Por qué querrías tal sobrecarga?

Considere

struct Member {};
struct Container { Member member };

Si desea mantener la Container vivo, mientras usas el Member, puedes hacer

std::shared_ptr<Container> pContainer = /* something */
std::shared_ptr<Member> pMember(pContainer, &pContainer->member);

Y solo hay que aferrarse a pMember (tal vez ponerlo en un std::vector<std::shared_ptr<Member>>)

O alternativamente, usando overload (9)

template< class Y > 
shared_ptr( const shared_ptr<Y>& r ) noexcept; 
  // Only exists if Y* is implicitly convertible to T*

Usted puede tener el compartir polimórfico

struct Base {};
struct Derived : Base {};

void operate_on_base(std::shared_ptr<Base>);

std::shared_ptr<Derived> pDerived = /* something*/
operate_on_base(pDerived);
 1
Author: Caleth,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-24 14:09:18