Lectura de Alexandrescu y wikipipidia Veo que la punta y el contador de referencia se almacenan en el montón. Entonces, ¿se menciona que el recuento de referencias es ineficiente ya que el contador debe asignarse en el montón? ¿Por qué no está almacenado en la pila?¿Por qué las implementaciones de puntero inteligente de C++ mantienen el contador de referencia en el montón junto con el puntero?
Respuesta
Porque lo perdería tan pronto como la instancia actual del puntero inteligente salga del alcance.
Un puntero inteligente se utiliza para simular objetos de almacenamiento automático que se asignaron dinámicamente. Los punteros inteligentes en sí mismos se administran automáticamente. Entonces, cuando uno es destruido, todo lo que almacena en el almacenamiento automático también se destruye. Pero no quiere perder el contador de referencia. Entonces lo almacena en almacenamiento dinámico.
No se puede almacenar en la pila porque una copia del objeto también daría lugar a una copia del recuento, lo que anularía su propósito.
Como otros han señalado, la pila no es un lugar apropiado para mantener la cuenta de referencia debido a que el objeto puede sobrevivir al marco de pila actual (en cuyo caso el contador de referencias se iría!)
Vale la pena señalando que algunas de las ineficiencias asociadas con poner el recuento de referencias en el montón se pueden superar al almacenarlas "juntas" con el objeto mismo. En el impulso, esto se puede lograr utilizando boost::make_shared (para shared_ptr) o boost::intrusive_ptr.
Existen diferentes tipos de punteros inteligentes, diseñados para diferentes propósitos. El puntero del que está hablando es un puntero inteligente compartido (std::shared_ptr
), que ayuda a compartir la propiedad de objetos desde varios lugares. Todas las copias de shared_ptr
incrementan y disminuyen la misma variable de contador, que se coloca en el montón, ya que debe estar disponible para todas las copias del shared_ptr
incluso después de que la primera copia muera.
Por lo tanto, shared_ptr
mantiene internamente dos punteros: al objeto y al contador. Pseudocódigo:
class SharedPointer<T> {
public:
// ...
private:
T* obj;
int* counter;
}
Por cierto, cuando se crea objeto con std::make_shared
, la implementación puede optimizar la asignación mediante la asignación de memoria suficiente para mantener tanto el contador y el objeto y luego construirlas de lado a lado.
Este truco en su extremo nos da un patrón de recuento de referencia intrusivo: el objeto mantiene internamente su contador y proporciona las funciones AddRef
y Release
para incrementarlo y disminuirlo. Puede usar puntero inteligente intrusivo, p. boost::intrusive_ptr
, que utiliza esta maquinaria y, por lo tanto, no necesita asignar otro contador por separado. Esto es más rápido en términos de asignaciones, pero requiere inyectar el contador a la definición de clase controlada.
Además, cuando no es necesario compartir la propiedad de objeto y sólo necesita controlar su tiempo de vida (de manera que se consigue cuando se devuelve la función destructed), se puede utilizar el con ámbito puntero inteligente: std::unique_ptr
o boost::scoped_ptr
. No necesita el contador por completo, ya que solo existe una copia del unique_ptr
.
- 1. Copiar el constructor con el puntero inteligente
- 2. C++ rendimiento de puntero inteligente
- 3. C++ puntero inteligente const correctness
- 4. ¿Por qué el puntero "this" en C++ es un puntero y no una referencia?
- 5. ¿Puedes declarar un puntero en el montón?
- 6. puntero inteligente Implementación en C
- 7. ¿Es el mango lo mismo que un puntero inteligente?
- 8. C++ pasar argumentos por referencia y el puntero
- 9. Pasando el argumento del puntero por referencia bajo C?
- 10. regla de tres con puntero inteligente?
- 11. Puntero C++ (Pase por referencia) Pregunta
- 12. paso por el puntero y Pasar por referencia
- 13. Objetos de C++: ¿Cuándo debo usar el puntero o referencia
- 14. pimpl-idioma en la plantilla; qué puntero inteligente?
- 15. Por qué no hay efecto de restringir el puntero
- 16. C++ puntero del vector de problema/referencia
- 17. Alias de puntero estricto: ¿es el acceso a través de un puntero/referencia 'volátil' una solución?
- 18. puntero como segundo argumento en lugar de devolver el puntero?
- 19. Cómo convertir/convertir el puntero a referencia en C++
- 20. excepción de captura por puntero en C++
- 21. C y el puntero notación
- 22. ¿Cuáles son las operaciones soportadas por puntero sin formato y puntero de función en C/C++?
- 23. ¿Cómo imprimo el valor del puntero de un objeto Go? ¿Qué significa el valor del puntero?
- 24. Diferencia entre el puntero en C++ y el tipo de referencia en C#
- 25. El puntero a puntero se bloquea en caso de que el puntero no
- 26. ¿Cuál es el constructor predeterminado para el puntero de C++?
- 27. ¿Por qué un puntero a un puntero es incompatible con un puntero a una matriz?
- 28. ¿Cuándo pasar por referencia y cuándo pasar por el puntero en C++?
- 29. ¿Por qué llamar a free() en un puntero asignado con 'nuevo' causa corrupción de montón?
- 30. Referencia a un puntero
¿Puedes mostrar un ejemplo de lo que estás describiendo? –
¿De qué otro modo lo harías? –
Tanto el "contador de referencia" como el "montón" son meros detalles de implementación.La verdadera cuestión es que la semántica de propiedad compartida solo se puede implementar con asignación dinámica. –