Entonces, finalmente encontré una falla extraña en mi software, que está sucediendo debido a un problema con el que me he encontrado antes:

m_member = Foo(var1, var2)

Me di cuenta de que está realizando una construcción de Foo usando var1 y var2, asignando esta instanciación de Foo a m_member a través de una asignación de copia, y luego está eliminando la instancia original. ¿Hay alguna forma de evitar este comportamiento y tener algo parecido a:

m_member(var1, var2);

Sé que esto es posible en las listas de inicializadores, pero desafortunadamente estoy modificando este miembro para un objeto que ya está construido. ¿Alguna idea?

1
Danny 10 ago. 2020 a las 07:06

2 respuestas

La mejor respuesta

Aquí hay algunas opciones, asumiendo que su problema proviene de la asignación de copia:

Use un tipo de puntero en su lugar

Cambie m_member para que sea un Foo*, o mejor un std::unique_ptr<Foo>, para que coincida mejor con el comportamiento anterior, y luego haga lo siguiente:

    m_member = std::make_unique<Foo>(var1, var2);

Ninguna copia, aún se destruirá al final de su alcance, y dada la descripción de su problema, esto podría significar que su recurso "Foo" será administrado de manera más eficiente como un puntero.

También podrías ...

Definir un operador de asignación de movimiento

Ahora, esto significa que debe definir los 5 grandes, pero definiendo una asignación de movimiento El operador le permitirá evitar la copia.

Foo& operator=(const Foo& other)
{
    // Copy the attributes you need to copy
    var1_ = other.var1_;
    var2_ = other.var2_;
    return *this;
}

Esto modificará eficazmente Foo en el lugar.

¿Arreglar la copia-asignación?

Ahora eso es realmente responder a su pregunta, pero un desarrollador desprevenido, por supuesto, esperaría que esto no se bloquee, y es muy posible que este problema aparezca en otro lugar, ya que la asignación de copia está presente mucho al escribir código y en algoritmos estándar. Pero hay múltiples razones por las que esto podría no ser posible, ¡así que te dejo ser el juez de eso!

2
Adrien Leravat 11 ago. 2020 a las 15:03

extraño bloqueo ... que está sucediendo porque ... Me he dado cuenta de que está realizando una construcción de Foo usando var1 y var2, asignando esta instanciación de Foo a m_member a través de una construcción de copia, y luego está eliminando la instancia original.

Si hacer esto provoca un bloqueo, entonces el diseño de la clase del miembro está roto. Probablemente (pero no puedo estar seguro) debido a que no se pudo aplicar un invariante de clase en el operador de asignación que sería necesario para evitar que el destructor tenga un comportamiento indefinido.

¿Hay alguna forma de evitar este comportamiento?

Si necesita asignar el miembro, debe asignarlo. Si mi sospecha es correcta, puede arreglar el programa arreglando el operador de asignación.

Si no necesita asignar el miembro, puede evitar este comportamiento al no asignarlo. Pero arregle el operador de asignación de todos modos.

Dado que no ha mostrado la clase, no puedo saber por qué está rota, pero lo más probable es que deba mirar el destructor y el operador de asignación y pensar en los casos que podrían causar que tengan un comportamiento indefinido.

¿Hay alguna forma de evitar este comportamiento y tener algo parecido a:

m_member(var1, var2);

Eso solo es posible cuando se inicializa el miembro.

2
eerorika 10 ago. 2020 a las 04:45