es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿Existe alguna forma de llamar al destructor de un elemento reemplazado al utilizar std::replace?

Tengo un vector de objetos en el que quiero reemplazar un elemento por otro. Usar std::replace parecía apropiado, así que lo intenté.

Sin embargo, estaba preocupado por el paradero del elemento reemplazado, así que hice algunas pruebas:

class A {
public:
A(const int ii): i(ii) {std::cout << “Constructor ” << i << std::endl;}
~A(){std::cout << “Destructor ” << i << std::endl;}
auto operator ==(const A& a){return i == a.i;}
int i;
};

int main() {
std::vector v;
v.reserve(4);
v.emplace_back(10);
v.emplace_back(20);
v.emplace_back(40);
v.emplace_back(30);
for(const auto& elt : v) {
std::cout << elt.i << ‘ ‘;
}
std::cout << std::endl;

std::replace(v.begin(), v.end(), v[2], A(25));
for(const auto& elt : v) {
    std::cout << elt.i << ' ';
}
std::cout << "End of program" << std::endl;

}

El tercer elemento del vector es reemplazado, pero como puede ver, el destructor del objeto reemplazado no se llama:

Constructor 10
Constructor 20
Constructor 40
Constructor 30
10 20 40 30
Constructor 25
10 20 25 30 End of program
Destructor 10
Destructor 20
Destructor 25
Destructor 30

Como el comportamiento es el mismo en cada compilador, supongo que está destinado, pero ¿hay alguna forma de que se llame al destructor en ese caso?

Ejemplo de prueba: https://godbolt.org/z/YTaKcrTEn

¡Gracias!

Tags:  ,

Answer

  1. Avatar for davy.ai

    La razón por la cual el destructor del objeto remplazado no se llama es porque std::replace remplaza los elementos en su lugar, sin realmente eliminar o destruir los viejos elementos. Los viejos elementos aun existen dentro del vector, pero ahora son iguales al nuevo elemento que proporcionó.

    Si desea eliminar y destruir el viejo elemento al reemplazarlo, puede usar std::replace_if con una función lambda que regrese verdadero para el elemento que desea reemplazar y falso para el resto. Dentro de la lambda, también puede destruir el viejo elemento antes de reemplazarlo con el nuevo elemento.

    Aquí hay un ejemplo:

    “`c++
    std::replace_if(v.begin(), v.end(), [](const A& a){ return a.i == 40; },
    { return A(25); });


    Esto encontrará el primer elemento en el vector con un valor de 40, lo destruirá y lo reemplazará con una nueva instancia de `A` con un valor de 25. Alternativamente, si realmente desea usar `std::replace` y que el viejo elemento sea destruido, puede simplemente llamar a `v.erase` después de `std::replace` para eliminar el viejo elemento: ```c++ auto it = std::find(v.begin(), v.end(), A(40)); if (it != v.end()) { *it = A(25); v.erase(it); }

    Esto encontrará el primer elemento en el vector con un valor de 40, lo reemplazará con una nueva instancia de A con un valor de 25 y luego lo eliminará del vector. Tenga en cuenta que eliminar un elemento de un vector puede ser costoso, especialmente si el vector es grande o contiene objetos complejos, así que use este método con precaución.

Comments are closed.