2011-12-05 9 views
6

Tengo un proyecto en el que necesito leer/escribir archivos de gran tamaño.Comportamiento específico de std :: string en visual studio?

He decidido usar ifstream :: read() para poner esos archivos en la memoria en una sola pasada, en una std :: cadena. (que parece ser la forma más rápida de hacerlo en C++: http://insanecoding.blogspot.com/2011/11/how-to-read-in-file-in-c.html y http://insanecoding.blogspot.com/2011/11/reading-in-entire-file-at-once-in-c.html)

Al cambiar entre archivos, que luego necesidad de "reiniciar" el std :: string usado como el búfer de memoria anterior (es decir, borrar el char [] buffer para liberar memoria)

traté:

std::string::clear() 
std::string::assign("") 
std::string::erase(0, std::string::npos) 
std::string::resize(0) 
std::string::reserve(0) 

pero, en Visual Studio 2008, esto no libera la memoria utilizada dentro de la std :: string en sí: su memoria intermedia subyacente no está desasignado

La única forma que encontré para eliminarlo es llamar a std :: string :: swap (std :: string ("")) para forzar el cambio de los búferes internos entre la std :: cadena real y la vacía en param.

Me parece que este comportamiento un poco extraño ...

yo sólo probamos en Visual Studio 2008, no sé si se trata de un comportamiento STL-estándar o si se trata de MSVC específica.

¿Me puede dar alguna pista?

+5

El intercambio es una forma estándar de hacer que los contenedores liberen memoria reservada. Y leer el archivo usando 'std :: string' está muy lejos de la forma óptima. –

+1

@VladLazarenko: estándar, y posiblemente el más rápido. – Nawaz

+3

¿Por qué ** espera ** que alguien desasigne el búfer? C++ 11 agrega el explícito 'shrink_to_fit()' para realizar una solicitud no vinculante de desasignación. –

Respuesta

4

Como comentó Vlad y Alf, std::string().swap(the_string) es la forma C++ 98 de liberar la capacidad de the_string, y the_string.shrink_to_fit() es la forma C++ 11.

En cuanto a por qué clear(), erase(), resize(), etc. no lo hagas, esta es una optimización para reducir las asignaciones cuando usas una cadena una y otra vez. Si clear() liberara la capacidad de la cadena, generalmente tendría que reasignar una cantidad similar de espacio en la siguiente iteración, lo que llevaría un tiempo la implementación puede ahorrar manteniendo la capacidad. Esta implementación no está garantizada por el estándar, pero es muy común en las implementaciones.

reserve() se documenta con

reserva de llamada() con un argumento res_arg menos de la capacidad() es, en efecto, una solicitud de contracción no vinculante. Una llamada con res_arg < = size() es, de hecho, una solicitud de reducción de ajuste no vinculante.

lo que implica que las implementaciones tienen más probabilidades de liberar la capacidad en una llamada reserve(). Si los estoy leyendo bien, libc++ y libstdC++ liberan espacio cuando llamas al reserve(0), pero es posible que la biblioteca de VC++ haya hecho la elección opuesta.

Editar: As penelope dice: std::string El comportamiento de esta aquí tiende a ser exactamente del mismo comportamiento de std::vector.

+1

Me gustaría agregar ... 'string's se comportan principalmente como' vector's ... y si agrega datos a un 'std :: vector', cuando su tamaño alcanza la capacidad reservada, su capacidad se duplica (y nada no tiene que suceder cuando el tamaño disminuye). De esta forma, el tiempo de inserción en la parte posterior del vector es más o menos constante sin dejar de ser eficiente en cuanto a la memoria: la reserva de memoria (operación lenta) se hace exponencialmente menos frecuente a lo largo del tiempo, mientras que el tamaño del vector nunca es más del doble de grande que el tamaño necesario – penelope

Cuestiones relacionadas