2011-06-29 17 views
10

NOTA: He encontrado que el origen del error no está realmente relacionado con el shared_ptr, simplemente ingeniosamente disfrazado como tal en el mensaje de error. Por lo tanto el siguiente es básicamente sin sentido (no las respuestas, están bien)Reenvío de un shared_ptr sin declaración de clase

-

Estoy teniendo algunos problemas para usar un shared_ptr (de impulso en el momento) donde tengo que simplemente enviar un puntero a otra función. Usando punteros nativos, la función intermedia no necesitaría tener acceso a la definición de la clase, pero al utilizar smart_ptr parece que sí. Hay alguna manera de evitar esto?

Por ejemplo, dada una función objetivo:

void func(shared_ptr<SomeClass> const & obj) 

El const & se encarga de una parte del problema, pero decir que tenemos una clase captador que obtiene el objeto de alguna otra clase, como:

shared_ptr<SomeClass> someClassInstance(); 

y aquí es donde me gustaría simplemente montar argumentos y transmitir a la función objetivo:

func(someClassInstance()); 

Con un puntero simple, este punto en el código podría simplemente usar una declaración directa de SomeClass, pero con un smart_ptr necesita tener la definición completa (presumiblemente como el smart_ptr podría necesitar eliminar la clase).

Ahora, si someClassInstance devolvieran un const &, este problema desaparecería ya que el código intermedio no estaría copiando ningún objeto. Sin embargo, la función getter debe devolver la copia por motivos de seguridad de hilos.

¿De todos modos puedo lograr este tipo de reenvío de parámetros de puntero inteligente sin necesidad de la definición de clase? Es decir, ¿puedo usar punteros inteligentes de la misma manera que lo haría con un puntero tradicional en esta circunstancia?

-

ACTUALIZACIÓN: Escribir una pequeña prueba las respuestas son correctas que una declaración hacia adelante es suficiente. Sin embargo, GCC sigue quejándose en una situación. Voy a tener que averiguar exactamente qué es lo que causa que falle (en esta situación particular).

¿Debo cerrar esta pregunta por ahora, o qué?

+3

¿Por qué quiere pasar un 'shared_ptr' por referencia? ¿Podría una referencia al tipo concreto bastar? También tiene algún tipo de concepto erróneo, 'shared_ptr' no requiere la definición completa del tipo para pasar, funciona con tipos incompletos. –

+0

no se puede hacer que 'func' sea una plantilla? – Nim

+0

Solo trato de pasar por referencia para evitar el problema (en algunos casos ayuda). Creo que necesito aislar mejor la situación en la que no funciona. –

Respuesta

14

Necesita al menos una declaración directa para T por cada mención de shared_ptr<T>.

Solo si usa unario shared_ptr::operator* y shared_ptr::operator->, es necesario. Debajo del capó, shared_ptr usa una combinación de polimorfismo en tiempo de compilación y en tiempo de ejecución, haciéndolo posible. Vea también this question para aprender sobre la "magia".

Ejemplo:

// frob.h 
#ifndef FROB_H 
#define FROB_H 

#include <shared_ptr> 

class Foo; 
void grind (std::shared_ptr<Foo>); 

#endif 

Nota que la forma canónica para pasar shared_ptr es por valor (es decir, quitar el const&).

+0

La declaración directa no es suficiente. Como la asignación por valor puede eliminar el objeto subyacente, necesita tener la definición completa. (Esta es la razón por la que uso const y para evitar este problema, pero no siempre funciona). –

+2

@ edA-qamort-ora-y Eso no es verdad. La asignación utiliza un eliminador personalizado que el constructor arregla. La declaración directa es suficiente para el uso de 'shared_ptr'; solo necesita la definición cuando llama a su constructor. –

+1

bajo el capó 'shared_ptr' usa una combinación de polimorfismo de tiempo de ejecución y de compilación, por lo que realmente no necesita una definición completa del tipo retenido, siempre que no use' shared_ptr :: operator-> 'y unario 'shared_ptr :: operator *'. Pruébalo :) –

3

Sí, los punteros compartidos están diseñados específicamente para trabajar con tipos incompletos (una función de asesino IMO). Requieren solo una declaración directa de una clase, no la definición de la clase. Desde Boost documentation:

Tenga en cuenta que scoped_ptr requiere que T sea un tipo completo en tiempo de destrucción, pero shared_ptr no lo hace.

Puede encontrar un debate sobre cómo funciona esto here.

Dado que los punteros compartidos deberían funcionar con tipos incompletos, ¿puede darnos un ejemplo específico (mínimo) en el que esto no funcione para usted?

Cuestiones relacionadas