print - string to int c++
c++ std:: ostringstream vs std:: string:: append (4)
Con la transmisión, puede hacer que su clase Myclass
anule la operación <<
para que pueda escribir
MyClass x;
ostringstream y;
y << x;
Para adjuntar, necesita tener un método ToString (o algo similar) ya que no puede anular la función de anexar de cadena.
Para algunas piezas de código use lo que le resulte más cómodo. Use el flujo para proyectos más grandes donde es útil poder simplemente transmitir un objeto.
En todos los ejemplos que usan algún tipo de búfer, veo que usan flujo en lugar de cadena. ¿Cuál es la diferencia entre std :: ostringstream y << operator y el uso de string.append? Cuál es más rápido y cuál usa menos recursos (memoria).
Una diferencia que sé es que puede generar diferentes tipos en el flujo de salida (como un entero) en lugar de los tipos limitados que acepta string :: append.
Aquí hay un ejemplo:
std::ostringstream os;
os << "Content-Type: " << contentType << ";charset=" << charset << "/r/n";
std::string header = os.str();
vs
std::string header("Content-Type: ");
header.append(contentType);
header.append(";charset=");
header.append(charset);
header.append("/r/n");
Obviamente, el uso de stream es más corto, pero creo que anexar devuelve la referencia a la cadena para que pueda escribirse así:
std::string header("Content-Type: ");
header.append(contentType)
.append(";charset=")
.append(charset)
.append("/r/n");
Y con el flujo de salida puedes hacer:
std::string content;
...
os << "Content-Length: " << content.length() << "/r/n";
Pero ¿qué pasa con el uso de la memoria y la velocidad? Especialmente cuando se utiliza en un gran bucle.
Actualizar:
Para ser más claros, la pregunta es: ¿Cuál debo usar y por qué? ¿Hay situaciones en las que se prefiere una o la otra? Para rendimiento y memoria ... bueno, creo que el punto de referencia es la única forma, ya que cada implementación podría ser diferente.
Actualización 2:
Bueno, no tengo una idea clara de qué debo usar de las respuestas, lo que significa que cualquiera de ellos hará el trabajo, más vector. Cubbi
hizo un buen punto de referencia con la adición de Dietmar Kühl de que la mayor diferencia es la construcción de esos objetos. Si está buscando una respuesta, también debe verificar eso. Esperaré un poco más por otras respuestas (busque la actualización anterior) y si no obtengo una, creo que aceptaré la respuesta de Tolga porque su sugerencia de usar vector ya está hecha antes, lo que significa que el vector debería tener menos recursos.
Si te preocupa la velocidad, debes hacer un perfil y / o prueba. En teoría, std::string::append
debe ser más lento, ya que es más simple (la secuencia tiene que tratar con la configuración regional, el formato diferente y ser más genérico). Pero, ¿qué tan rápido es una solución u otra que realmente puedes realizar solo mediante pruebas?
std::ostringstream
no se almacena necesariamente como una matriz secuencial de caracteres en la memoria. Realmente necesitaría tener una matriz continua de caracteres al enviar esos encabezados HTTP y eso podría copiar / modificar el búfer interno para hacerlo secuencial.
std::string
usando std::string::reserve
apropiado no tiene ninguna razón para actuar más lento que std::ostringstream
en esta situación.
Sin embargo, std::ostringstream
es probablemente más rápido de agregar si no tiene ni idea del tamaño que tiene que reservar. Si usa std::string
y su cadena crece, eventualmente requiere la reasignación y copia de todo el búfer. Sería mejor usar one std::ostringstream::str()
para hacer que los datos sean secuenciales a la vez en comparación con las múltiples reasignaciones que de lo contrario ocurrirían.
PS Pre-C ++ 11 std::string
tampoco tiene que ser secuencial, mientras que casi todas las bibliotecas lo implementan como secuencial. Podrías arriesgarte o usar std::vector<char>
lugar. Necesitarías usar lo siguiente para adjuntar:
char str[] = ";charset=";
vector.insert(vector.end(), str, str + sizeof(str) - 1);
std::vector<char>
sería mejor para el rendimiento porque probablemente es más barato de construir, pero probablemente no tenga importancia en comparación con std::string
y el tiempo real que demoran en construirlo. He hecho algo similar a lo que estás intentando y fui con std::vector<char>
antes. Simplemente por razones lógicas; El vector parecía encajar mejor en el trabajo. Realmente no quieres manipulaciones de cuerdas o tal. Además, los puntos de referencia que hice más tarde demostraron que funcionaba mejor o tal vez solo porque no implementé las operaciones lo suficientemente bien con std::string
.
Mientras selecciona, el contenedor que tiene los requisitos para sus necesidades y las funciones adicionales mínimas por lo general hace el mejor trabajo.
la construcción de un objeto de flujo es una operación significativamente más compleja que la construcción de un objeto de cadena, ya que tiene que mantener (y, por lo tanto, construir) su miembro std::locale
, entre otras cosas, necesario para mantener el estado (pero la configuración regional es por un gran número margen más pesado).
Anexar es similar: ambos mantienen una matriz contigua de caracteres, ambos asignan más cuando se excede la capacidad. Las únicas diferencias en las que puedo pensar es que al agregar a un flujo, hay una función de miembro virtual llamada por desbordamiento (además de la asignación / copia de memoria, que domina el manejo del desbordamiento de todos modos), y el operator<<
tiene que hacer algunas comprobaciones adicionales del estado de la corriente.
Además, tenga en cuenta que está llamando a str (), que copia la cadena completa una vez más, por lo que, en función de lo que esté escrito su código, el ejemplo de flujo hace más y debería ser más lento.
Vamos a probar:
#include <sstream>
#include <string>
#include <numeric>
volatile unsigned int sink;
std::string contentType(50, '' '');
std::string charset(50, '' '');
int main()
{
for(long n = 0; n < 10000000; ++n)
{
#ifdef TEST_STREAM
std::ostringstream os;
os << "Content-Type: " << contentType << ";charset=" << charset << "/r/n";
std::string header = os.str();
#endif
#ifdef TEST_STRING
std::string header("Content-Type: ");
header.append(contentType);
header.append(";charset=");
header.append(charset);
header.append("/r/n");
#endif
sink += std::accumulate(header.begin(), header.end(), 0);
}
}
eso es 10 millones de repeticiones
En mi Linux, me sale
stream string
g++ 4.8 7.9 seconds 4.4 seconds
clang++/libc++ 11.3 seconds 3.3 seconds
así que, para este caso de uso, en estas dos implementaciones, las cadenas parecen funcionar más rápido, pero obviamente ambas formas tienen mucho que mejorar (reservar () la cadena, mover la construcción de la secuencia fuera del bucle, usar una secuencia que no requiera copiando para acceder a su buffer, etc)