VS2019 | C++ | Punteros compartidos | Advertencia del compilador: El puntero apunta a memoria asignada en la pila.
He heredado un montón de código C++, saturado de std::shared_ptrs, la mayoría [¿todos?] de los cuales son innecesarios y, sospecho, están degradando el rendimiento. No es factible cambiar todo de una vez, así que estoy cambiando el código por tramos y realizando pruebas de rendimiento.
Un problema con el que me encuentro es la interfaz en la jerarquía de métodos entre mi nuevo código de puntero “raw” y el underlying de shared_ptr. Un ejemplo ficticio (sé que se podría simplificar…):
SomeObject *MyClass::GetSomeObject(const std::string& aString)
{
//para los métodos del shared pointer subyacente
std::shared<em>ptr<std::string> tmpString = make</em>shared<std::string>(aString);
//llamar al método usando mi shared pointer local
std::shared_ptr<SomeObject> someObj = GetTheObject(tmpString);
//La línea de abajo da una advertencia del compilador: "El puntero apunta a una memoria asignada en la pila"
return someObj.get(); // un puntero a un objeto en std::map
}
Sé que GetTheObject()
está devolviendo un puntero a un objeto en un std::map
persistente, por lo que la memoria estará en buen estado después de que salgamos de GetSomeObject()
y el shared pointer [y su puntero raw envuelto] hayan salido de ámbito.
No tengo la costumbre de ignorar advertencias, ASÍ QUE:
Preguntas:
1. ¿Es la advertencia porque el compilador está preocupado por el ámbito del shared pointer en lugar del objeto apuntado? [es decir, ¿puedo ignorarla en este caso?]
- Si es un problema real, ¿hay alguna forma ingeniosa de solucionarlo (que no involucre construir clases envolventes y demás soluciones alternativas…)?
davy.ai
Si deseas evitar la advertencia sin construir clases de envoltura o modificar significativamente el código existente, puedes usar una sobrecarga del constructor de
shared_ptr
que toma un eliminador personalizado como parámetro. En este caso, podrías crear unshared_ptr
con un eliminador personalizado que no haga nada, luego usarlo para envolver el puntero sin procesar devuelto porsomeObj.get()
, de modo que la memoria a la que apunta sea gestionada por el mismo mecanismo que el resto de losshared_ptr
en la base de código. Esto se vería algo así:Aquí, la función lambda pasada como eliminador personalizado toma un
SomeObject*
como su parámetro y no hace nada con él, lo que efectivamente lo convierte en una operación sin efecto.Sin embargo, hay que tener en cuenta que este enfoque aún puede tener un cierto costo adicional debido a la gestión adicional de shared pointer involucrada, por lo que no necesariamente mejorará el rendimiento. Además, modificar el código existente para eliminar los shared pointer innecesarios aún puede ser una mejor solución a largo plazo.