2010-06-03 18 views
5

¿Hay alguna manera de saber si un objeto es un objeto constante u objeto regular, por ejemplo, considere la siguiente claseobjeto constante y constructor const

class String 
{ 
    String(const char* str); 
}; 

si el usuario crear un objeto constante de String entonces no hay razón para copiar la cadena nativa pasada y eso porque no hará ninguna manipulación sobre él, lo único que hará es obtener el tamaño de cadena, búsqueda de cadenas y otras funciones que no cambiarán la cadena.

+5

No hay forma de saberlo. De hecho, 'const' solo se aplica una vez que el objeto se inicializa (el constructor finaliza) y se detiene una vez que se ingresa el destructor. – GManNickG

Respuesta

8

Existe una muy buena razón para copiar: no puede saber que la vida útil del const char * es la misma que la del objeto String. Y no, no hay forma de saber que estás construyendo un objeto const.

2

Lamentablemente, C++ no proporciona una forma de hacer lo que está intentando. Simplemente pasar un const char * no garantiza la vida útil de la memoria a la que se apunta. Considere:

char * a = new char[10]; 
char const *b = a; 
String c (b); 
delete[] a; 
// c is now broken 
2

No hay forma de que usted lo sepa. Podría escribir una clase que interactúe estrechamente con String y que cree una cadena constante apuntando a un búfer externo (haciendo que el constructor correspondiente sea privado y que la clase que interactúa sea una clase anidada o un amigo de String).

Si lo único que te preocupa es la administración dinámica de la memoria en una cadena constante potencialmente pequeña, puedes implementar Small String Optimization (también Small Object/Buffer Optimization). Funciona teniendo un búfer incrustado en su clase de cadena y copiando cada cadena hasta un tamaño predefinido en ese búfer, y cada cadena que es más grande en un almacenamiento asignado dinámicamente (la misma técnica es utilizada por boost::function para almacenar objetos de función de tamaño pequeño) .

class String { 
    union { 
    char *dynamicptr; 
    char buffer[16]; 
    }; 
    bool isDynamic; 
}; 

hay técnicas inteligentes para almacenar incluso la longitud de la cadena incrustada en el propio tampón (almacenar su longitud como buffer[15] y engaños similares).

0

Lo que estás buscando es básicamente una cadena COW (copiar al escribir). Tales cosas son completamente posibles, pero hacer que funcionen bien es algo no trivial. En un entorno multiproceso, obtener un buen rendimiento puede ir más allá de lo no trivial en el rango decididamente difícil.

1

Puede usar const_string para hacer lo que está buscando. Sin embargo, incluso con la cadena const, tienes que "decirle" que la cadena no necesita ser copiada.

const char* foo = "c-string"; 
boost::const_string bar(foo); // will copy foo 
boost::const_string baz(boost::ref(foo)); // assumes foo will always be a valid pointer. 
1

si el usuario crear un objeto constante de la cadena, entonces no hay razón para copiar la cadena nativa pasado y que ya no va a hacer ningún tipo de manipulación en él, lo único que hará es conseguir tamaño de la cadena , búsqueda de cadenas y otras funciones que no cambiarán la cadena.

Oh sí, hay. Solo que es como const no significa que realmente esté const afuera de la llamada del constructor, y especialmente no significa que no se destruirá mientras el objeto de cadena todavía exista. La palabra clave const para un argumento de función solo significa que la función no lo modificará ni eliminará (intentar implementar una función que modifique un argumento const generará un error de compilación), pero no hay forma de que la función sepa lo que sucede afuera .

Cuestiones relacionadas