¿ std::make_uniqueTiene algún beneficio de eficiencia como std::make_shared?
En comparación con la construcción manual std::unique_ptr:
std::make_unique<int>(1); // vs
std::unique_ptr<int>(new int(1));
c++
c++11
c++14
smart-pointers
unique-ptr
NFRCR
fuente
fuente

make_sharedTiene alguna eficiencia sobre solo escribir el código de mano larga?make_sharedpuede asignar tanto el espacio para el objeto como el espacio para el bloque de control juntos en una sola asignación. El costo de esto es que el objeto no se puede desasignar por separado del bloque de control, por lo que si usaweak_ptrmucho, puede terminar usando más memoria.Respuestas:
La motivación detrás
make_uniquees principalmente doble:make_uniquees seguro para crear temporarios, mientras que con el uso explícitonewdebe recordar la regla sobre no usar temporarios sin nombre.La adición de
make_uniquefinalmente significa que podemos decirle a la gente que 'nunca' use ennewlugar de la regla anterior a "nunca" usar,newexcepto cuando realice ununique_ptr".También hay una tercera razón:
make_uniqueno requiere uso de tipo redundante.unique_ptr<T>(new T())->make_unique<T>()Ninguno de los motivos implica mejorar la eficiencia del tiempo de ejecución de la manera en que lo
make_sharedhace (debido a evitar una segunda asignación, a costa de un uso de memoria pico potencialmente mayor).* Se espera que C ++ 17 incluya un cambio de regla que significa que esto ya no es inseguro. Véanse los documentos del comité C ++ P0400R0 y P0145R3 .
fuente
std::unique_ptrystd::shared_ptres por eso que podemos decirle a la gente que "nunca lo usenew".make_sharedy también lomake_uniquees la pieza final que faltaba anteriormente.f:f(unique_ptr<T>(new T), function_that_can_throw());- citar la respuesta: El compilador se le permite a la llamada (en orden):new T,function_that_can_throw(),unique_ptr<T>(...). Obviamente, si enfunction_that_can_throwrealidad tira, entonces goteas.make_uniquePreviene este caso. Entonces, mi pregunta está respondida.std::make_uniqueystd::make_sharedestán ahí por dos razones:std::unique_ptrostd::shared_ptrconstructores. (Vea la sección de Notas aquí .)No se trata realmente de la eficiencia del tiempo de ejecución. Hay un poco sobre el bloque de control y la
Tasignación de todos a la vez, pero creo que eso es más una bonificación y menos una motivación para que estas funciones existan.fuente
std::make_sharedasegurará que al menos uno de ellos quede envuelto en el puntero inteligente antes de que ocurra la otra asignación de memoria, por lo tanto, no habrá fugas.Una razón por la que tendría que usar
std::unique_ptr(new A())ostd::shared_ptr(new A())directamente en lugar destd::make_*()no poder acceder al constructor de la claseAfuera del alcance actual.fuente
Considerar llamada de función
Supongamos que lo nuevo
A()tiene éxito, pero lo nuevoB()arroja una excepción: lo detecta para reanudar la ejecución normal de su programa. Desafortunadamente, el estándar C ++ no requiere que el objeto A se destruya y se desasigne su memoria: la memoria se pierde silenciosamente y no hay forma de limpiarla. Al envolver A y B enstd::make_uniquesusted, está seguro de que no ocurrirá la fuga:El punto aquí es que
std::make_unique<A>ystd::make_unique<B>ahora son objetos temporales, y la limpieza de los objetos temporales está especificada correctamente en el estándar C ++: sus destructores se activarán y se liberará la memoria. Entonces, si puede, siempre prefiera asignar objetos usandostd::make_uniqueystd::make_shared.fuente