2008-12-12 16 views

Respuesta

6

Sólo unos pocos de la parte superior de mi cabeza:

  • Navegar por en archivos mapeados en memoria.
  • Las llamadas a la API de Windows donde tiene que sobreasignar (como un LPBITMAPINFOHEADER).
  • Cualquier código en el que esté trabajando en una memoria arbitraria (VirtualQuery() y similares).
  • Casi en cualquier momento que esté usando reinterpret_cast <> en un puntero.
  • Cada vez que utiliza la ubicación nueva.

El hilo común aquí es "cualquier situación en la que necesite tratar una parte de la memoria como algo más que un recurso sobre el que tiene control de asignación".

+1

Cada vez que necesito asignar memoria (digamos para mantener un BITMAPINFOHEADER con bytes adicionales al final), usaría std :: vector si fuera posible, entonces no hay que preocuparse por la eliminación y si una API de Windows me dijera mi asignación la memoria no es suficiente, std :: vector :: resize() es dulce. –

+0

Por supuesto. Todavía puede usar contenedores estándar o punteros inteligentes para administrar la memoria subyacente cuando sea posible. El punto es cuando vas a hablar con una API de Windows, vas a convertir a un puntero sin formato, que es lo que hizo la pregunta original. –

+0

También para interactuar con el "exterior". Si su usuario solicita un búfer, obtiene un búfer, no un puntero inteligente. –

4

En estos días he abandonado prácticamente todo el uso de punteros sin formato. Incluso he comenzado a buscar en nuestra base de códigos lugares donde se usaron punteros sin procesar y los cambié a una variante de puntero inteligente. Es increíble la cantidad de código que he podido eliminar haciendo este simple acto. Se desperdicia tanto código en la administración de por vida de los punteros de C++ sin procesar.

Los únicos lugares donde no uso punteros son para un par de escenarios de interoperabilidad con otras bases de código sobre las que no tengo control.

2

Todavía utilizo punteros regulares en código sensible a los recursos u otro código que necesita una huella pequeña, como ciertas excepciones, donde no puedo suponer que ningún dato sea válido y también debo suponer que también me estoy quedando sin memoria.

La memoria administrada casi siempre es superior a la cruda, de lo contrario, significa que no tiene que lidiar con eliminarla en el lugar correcto, pero aún tiene un gran control sobre los puntos de construcción y destrucción de sus punteros.

Ah, y hay otro lugar para utilizar punteros primas:

boost::shared_ptr<int> ptr(new int); 
+0

Pensé que no había sobrecarga con el impulso: clases de puntero? ¿El compilador no optimiza todo? – ApplePieIsGood

+0

No hay una gran cantidad de sobrecarga en las clases de punteros con ámbito, pero tiene que existir, y los punteros compartidos necesitan un recuento de referencias y los mecanismos asociados. Siempre sigo la regla 1; perfil primero, luego optimice. – coppro

+0

No puedo pensar en una sola vez de 15 años de codificación C++ que alguna vez haya necesitado para asignar explícitamente una sola int en el montón. Una matriz de int: s es otra cuestión, pero siempre hay std :: vector . –

1

Si tiene estructuras circulares de datos, por ejemplo, algunos puntos a B y B puntos de nuevo a una, no se puede utilizar utilizar ingenuamente punteros inteligentes para A y B, ya que los objetos solo se liberarán de trabajo extra. Para liberar la memoria, debe borrar manualmente los punteros inteligentes, lo cual es casi tan malo como eliminar los punteros inteligentes que se eliminan.

Es posible que esto no ocurra muy a menudo, pero supongamos que tiene un objeto principal que tiene punteros inteligentes para un grupo de objetos secundarios. En algún momento a lo largo del camino, alguien necesita buscar un Parent for a Child, por lo que agregan un puntero inteligente a Child que apunta al padre. En silencio, la memoria ya no se libera.

Se requiere cierto cuidado. Los punteros inteligentes no son equivalentes a la recolección de basura.

+1

Esto es lo que boost :: weak_ptr es para, si lo tiene. Por lo tanto, aún puede usar punteros inteligentes en lugar de crudos, pero no todos los punteros inteligentes serán shared_ptr. –

+0

Absolutamente boost :: weak_ptr es otra forma de resolver los problemas de referencia circular, pero creo que mi punto sigue siendo válido: hay que prestar atención y no solo usar ciegamente los punteros inteligentes que tenga. –

+0

Supongo que estoy asumiendo que cuando el interlocutor dice "indicadores inteligentes de boost adoptado", se refiere a todos ellos, se usa de forma adecuada, no solo shared_ptr se usa para todo. Tiene razón en que no todos los lectores apreciarán esto :-) –

7

No utilizo shared_ptr casi en absoluto, porque evito la propiedad compartida en general. Por lo tanto, uso algo como boost::scoped_ptr para "poseer" un objeto, pero todas las demás referencias serán punteros sin formato. Ejemplo:

boost::scoped_ptr<SomeType> my_object(new SomeType); 
some_function(my_object.get()); 

Pero some_function se ocupará de un puntero en bruto:

void some_function(SomeType* some_obj) 
{ 
    assert (some_obj); 
    some_obj->whatever(); 
} 
+1

Me pegó - Iba a decir que pasar por puntero sin formato puede ser utilizado por convención para implicar que el destinatario no retendrá una referencia al objeto (o al menos no de una manera que afecte la administración de recursos). –

+0

¿Cómo se puede retener una referencia al objeto de una manera que no afecte la gestión de recursos?Una vez que se destruye el recurso, el retenedor de esa referencia ahora debe conocer el hecho, ¿verdad? – ApplePieIsGood

+2

Se trata de ámbitos. Ponga al propietario en el alcance más amplio del objeto que se va a utilizar, y luego simplemente pase punteros a él dentro de ese alcance. No se permite que ninguna referencia viva en un ámbito más amplio que el propietario y, por lo tanto, se garantiza que apunta a un objeto válido. –

2

todavía uso punteros primas en los dispositivos que se han mapeado en memoria IO, tales como sistemas integrados, en los que tienen un puntero inteligente doesn' Realmente tiene sentido porque nunca lo necesitará o podrá delete.

4

La principal diferencia entre el C++ "moderno" y el antiguo * es el uso cuidadoso de invariantes de clase y encapsulamiento. Un código bien organizado tiende a tener menos punteros volando. Estoy casi tan nervioso nadando en shared_ptrs como lo estaría en noticias y eliminaciones.

Estoy esperando unique_ptr en C++ 0x. Creo que eso ordenará los pocos (inteligentes) indicadores que todavía vagan por la naturaleza.

* todavía por desgracia muy común

4

Ciertamente cualquier momento que está tratando con una biblioteca legado o API que necesita para pasar un puntero prima, aunque es probable que acaba de extraer de su puntero inteligente temporalmente.

De hecho, siempre es seguro pasar un puntero sin formato a una función, siempre que la función no intente mantener una copia del puntero en una variable global o miembro, o intente eliminarla. Con estas restricciones establecidas, la función no puede afectar la vida útil del objeto, y la única razón para un puntero inteligente es administrar la duración del objeto.

1

Estoy escribiendo C++ que tiene que coexistir con Objective C (usando Objective C++ para tender un puente). Dado que los objetos C++ declarados como parte de las clases de Objective C++ no tienen llamados constructores o destructores, no se pueden mantener realmente allí en los punteros inteligentes.

Por lo tanto, suelo usar punteros sin formato, aunque a menudo con boost :: intrustive_ptr y un recuento interno de ref.

+0

¿Es esto correcto? Mi lectura del doco dice que se llama al constructor sin argumentos, y se llama al destructor cuando se destruye el objeto Objective C. Tal vez las cosas han cambiado/mejorado desde que publicaste. –

+0

Las cosas han cambiado/mejorado desde que publiqué :-) De hecho, justo antes de publicar, ya estaba un poco desactualizado. – philsquared

0

No es que yo lo haría, pero necesita punteros sin procesar para implementar, por ejemplo, una lista vinculada o un gráfico. Pero sería mucho más inteligente usar std::list<> o boost::graph<>.

Cuestiones relacionadas