C ++ devolviendo objetos persistentes

7

Actualmente estoy tratando de aprender las mejores prácticas en C ++ después de provenir de un fondo de C #. Entiendo que hay tres formas de manejar objetos:

  • Por valor (los objetos se copian o mueven cuando se pasan dentro y fuera de las funciones)
  • Por referencia
  • Por puntero compartido o único (los punteros en bruto están mal vistos a menos que realmente los necesites)

En general, considero que es una buena práctica evitar el uso de punteros compartidos, pero como estoy desarrollando una gran cantidad de código recientemente, encuentro que inicialmente defino algo como un tipo de valor y luego tengo que convertirlo en un elemento compartido. puntero. ¡Esta situación ocurre con tanta frecuencia que casi todos los objetos de mi sistema están en un puntero compartido! Esto parece mal.

La mayoría de mis clases tienen este aspecto:

class Container
{
public:
    // ...other functions

    std::shared_ptr<Thing> GetThing() const;
    std::vector<std::shared_ptr<Thing>> GetThings() const;

private:
    std::shared_ptr<Thing> thing;
    std::vector<std::shared_ptr<Thing>> things;
}

Inicialmente, esta clase habría contenido objetos de valor de tipo Cosa, pero luego otras clases necesitan acceso a estos objetos y, por lo tanto, para evitar copiarlos cuando se devuelven desde las funciones 'getter', los he puesto en punteros compartidos. Esto significa que si se producen cambios en estos objetos, su estado será coherente con el contenedor y los objetos que actualmente acceden a las 'cosas'.

¿Por qué esto se siente mal y cómo puedo mejorar este enfoque? ¿Cuál es la forma correcta de 'C ++' para hacer esto?

    
pregunta innova 22.10.2015 - 17:09

3 respuestas

6

No está claro lo que haces con esos objetos.

Si desea copiar la clase que no se puede copiar, el uso de shared_ptr está bien como lo hizo.

Si desea copiar objetos, devuelva un valor.

Si solo desea proporcionar acceso a esos objetos, use referencias:

class Container
{
public:
    // ...other functions

    const Thing& GetThing() const;
    const std::vector<Thing>& GetThings() const;

private:
    Thing thing;
    std::vector<Thing> things;
};
    
respondido por el BЈовић 22.10.2015 - 17:40
2

Devuelve / pasa por const. ref antes de cambiar a shared_ptr . Te dejan pasar por referencia sin permitirles cambiar el objeto. Esto requiere que tenga cuidado de mantener la corrección constante en todo momento.

class Container
{
public:
    // ...other functions

    const Thing& GetThing() const;
    Thing& GetThing();

    const std::vector<Thing>& GetThings() const;
    std::vector<Thing>& GetThings();

private:
    Thing thing;
    std::vector<Thing> things;
}

Lo que es importante es el razonamiento sobre la propiedad. Con almacén por valor y paso por referencia, usted sabe exactamente qué posee el objeto y sabe quién es el responsable de destruirlo.

    
respondido por el ratchet freak 22.10.2015 - 17:36
1

Parece que está haciendo esto porque desea modificar los valores internos dentro de Container . Así que estás haciendo algo como:

void foo(Container &container) {
   container.GetThing().SetFoo(12);
}

El problema es que se supone que no debes modificar el estado interno de Container de esta manera. Solo los métodos en Container deberían modificarlo. Por lo tanto, esta función probablemente debería ser un contenedor de información privilegiada.

void Container::foo() {
    thing.SetFoo(12);
}

Si realmente debes modificar algo fuera de Container , deberías preferir algo más explícito:

void foo(Container &container) {
    Thing thing = container.GetThing();
    thing.SetFoo(12);
    container.SetThing(thing);
}

Pero tener métodos Get / Set para piezas internas de estado en Container es un olor de código. Sugiere que tienes otro código que realmente debería ser parte de Container .

    
respondido por el Winston Ewert 22.10.2015 - 17:55

Lea otras preguntas en las etiquetas