2011-07-14 12 views
16

Supongamos que tengo una matriz de caracteres, que he asignado en el montón, y que quiero convertir en std :: string. Actualmente estoy haciendo lo siguiente:¿Cómo crear una cadena std :: directamente desde una matriz char * sin copiar?

char *array = new char[size]; 
WriteIntoArray(array, size); 
std::string mystring(array); 
delete[] array; 
return mystring; // or whatever 

Por lo que he leído en Internet (http://www.cplusplus.com/reference/string/string/string/), el constructor de cadenas realiza una copia de la memoria intermedia lo paso, dejándome para liberar la memoria intermedia (después, la libera de cuerda su buffer interno). Lo que me gustaría hacer es asignar mi buffer, transferir el control de él a la cadena y luego liberarlo de mi buffer cuando se destruya.

La pregunta initializing std::string from char* without copy parecía prometedora, pero mi código se basa en llamadas API ("WriteIntoArray" en el ejemplo anterior) que tienen que escribir en una matriz de caracteres, así que tengo que crear un búfer char * de estilo C y no puedo convertir mi código para usar solo operaciones de cadenas incorporadas (que fue la respuesta sugerida).

¿Hay alguna forma estándar de hacerlo, o debería simplemente escribir mi propia clase de cadena (ugh)? ¡Gracias!

Respuesta

15

Si estás usando una aplicación C++ 0x conforme, o una de las muchas bibliotecas de C++ que garantizan el almacenamiento contiguo para std::string, entonces se puede obtener un char* que apunta directamente al almacenamiento utilizado por su std::string.

Por ejemplo:

std::string mystring; 
mystring.resize(size); 
WriteIntoArray(&mystring[0], size); 
return mystring; 

Es posible que tenga que pensar cuidadosamente acerca de un terminador nulo, sin embargo.

+1

Nº de reserva() se reserva el espacio, pero no pertenece a la cadena (todavía). El acceso a [0] o a [1] sigue siendo UB. Si eliges el tamaño(), seguirá siendo cero. Lo que realmente quiere es cambiar el tamaño() –

+2

No puede usar reserva(), debe usar resize(). Y luego descubra un tamaño adecuado() después de la llamada. –

+2

'reserve' debe ser' resize'. ¿Qué significa realmente "pensar cuidadosamente sobre un terminador nulo"? ¿Hay alguna garantía en cuanto a si el conjunto apuntado por '& mystring [0]' debe terminar en nulo? ¿Es 'std :: string' el responsable de garantizar que ese terminador esté allí? Si 'WriteIntoArray' escribe un terminador nulo, ¿debería eliminarse? (Lo pregunto porque no sé qué garantiza y requiere 'std :: string'.) –

5

No se puede std :: string posee el puntero y, por lo tanto, copia los datos en un espacio que asigna.

Lo que podría hacer es:

std::string mystring(size, ' '); 
WriteIntoArray(&mystring[0], size); 
return mystring; // or whatever 
Cuestiones relacionadas