Estoy usando una biblioteca que contiene muchas clases creadas usando el modismo PIMPL . Lo que encontré mal, en mi opinión, es que esas clases se implementan usando un std::shared_ptr para la implementación. Esto significa que los objetos se "comparten implícitamente". Mi pregunta es: ¿es esta la forma correcta de implementar PIMPL? ¿O PIMPL y "implícitamente compartido" son dos modismos diferentes y, por lo tanto, no deberían mezclarse de forma predeterminada? ¿Cuál es la forma correcta de manejar la semántica de copia?

0
nyarlathotep108 27 ene. 2016 a las 13:30

2 respuestas

La mejor respuesta

En mi opinión, la forma correcta de implementar pimpl es usar std::unique_ptr. Es más eficiente y el objeto pimpl debe ser propiedad exclusiva de la clase visible, no compartirse (y no tiene que preocuparse por copiar semántica).

PIMPL y "implícitamente compartido" son dos expresiones idiomáticas diferentes.

Si aún tiene que usar std::shared_ptr para pimple, tendrá que definir explícitamente las operaciones de asignación de copia (porque el compilador no podrá generar las correctas).

6
coincoin 27 ene. 2016 a las 10:43

Como dijo coincoin, use un unique_ptr en lugar de un shared_ptr. Si desea que su clase se pueda copiar, siempre puede llamar al constructor de copia de su objeto pimpl en el constructor de copia de su clase visible.

class A {
    class impl;
    std::unique_ptr<impl> pimpl;
public:
    A(int x);
    A(A const& old);
    ...
};

Implementación:

class A::impl {
    int x;
public:
    impl(int x)
        : x(x)  {}
    impl(impl const& old)
        : x(old.x) {}
};

A::A(int x)
    : pimpl(std::make_unique<impl>(x)) {}

A::A(A const& old)
    : pimpl(std::make_unique<impl>(*old.pimpl)) {}
0
Florian Keßeler 27 ene. 2016 a las 10:48