Ventajas de usar literal definido por el usuario para cadenas en lugar de literal de cadena
El tema de cadenas en la Documentación SO solía decir, en la sección de Observaciones:
Desde C++14, en lugar de usar
"foo"
, se recomienda usar"foo"s
, ya ques
es un literal de cadena, que convierteconst char *
"foo"
tostd::string
"foo"
.
La única ventaja que veo usando
std::string str = "foo"s;
En lugar de
std::string str = "foo";
Es que en el primer caso el compilador puede realizar copy-elision (creo), que sería más rápido que la llamada del constructor en el segundo caso.
Sin embargo, esto (aún no) está garantizado, por lo que el primero también podría llamar a un constructor, el constructor de copia.
Ignorando casos donde es requerido para usar std::string
literales como
std::string str = "Hello "s + "World!"s;
¿Hay algún beneficio de usar std::string
literales en lugar de const char[]
literales?
4 answers
Si eres parte de la multitud "Casi Siempre Auto", entonces la UDL es muy importante. Te permite hacer esto:
auto str = "Foo"s;
Y así, str
será un verdadero std::string
, no un const char*
. Por lo tanto, le permite decidir cuándo hacer qué.
Esto también es importante para la deducción de tipo de retorno automático:
[]() {return "Foo"s;}
O cualquier forma de deducción de tipo, realmente:
template<typename T>
void foo(T &&t) {...}
foo("Foo"s);
La única ventaja que veo usando [...] en lugar de [...] es que en el primer caso, el compilador puede realizar copy-elision (creo), que sería más rápido que la llamada del constructor en el segundo caso.
Copy-elision no es más rápido que la llamada del constructor. De cualquier manera, estás llamando a uno de los constructores del objeto. La pregunta es cuál :
std::string str = "foo";
Esto provocará una llamada al constructor de std::string
que toma un const char*
. Pero dado que std::string
tiene que copiar la cadena en su propio almacenamiento, debe obtener la longitud de la cadena para hacerlo. Y ya que no sabe la length, este constructor se ve obligado a usar strlen
para obtenerlo (técnicamente, char_traits<char>::length
, pero eso probablemente no va a ser mucho más rápido).
Por el contrario:
std::string str = "foo"s;
Esto utilizará la plantilla UDL que tiene este prototipo:
string operator "" s(const char* str, size_t len);
Vea, el compilador conoce la longitud de un literal de cadena. Así que el código UDL se pasa un puntero a la cadena y un tamaño. Y por lo tanto, puede llamar al constructor std::string
que toma un const char*
y a size_t
. Así que no hay necesidad de calculando la longitud de la cadena.
El consejo en cuestión no es que vayas por ahí y conviertas cada uso de un literal en la versión s
. Si estás de acuerdo con las limitaciones de un array de char
s, úsalo. El consejo es que, si vas a almacenar ese literal en un std::string
, es mejor hacerlo mientras siga siendo un literal y no un nebuloso const char*
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-28 20:27:11
El consejo de usar "blah"s
no tiene nada que ver con la eficiencia y todo tiene que ver con la corrección para el código novato.
Los novatos de C++ que no tienen un fondo en C, tienden a asumir que "blah"
resulta en un objeto de algún tipo de cadena razonable. Por ejemplo, para que uno pueda escribir cosas como "blah" + 42
, que funciona en muchos lenguajes de escritura. Con "blah" + 42
en C++, sin embargo, uno solo incurre en un Comportamiento Indefinido, dirigiéndose más allá del final de la matriz de caracteres.
Pero si ese literal de cadena es escrito como "blah"s
entonces uno obtiene un error de compilación, que es mucho preferible.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-28 03:22:25
Además, UDL facilita tener \0
en la cadena
std::string s = "foo\0bar"s; // s contains a \0 in its middle.
std::string s2 = "foo\0bar"; // equivalent to "foo"s
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-09 09:09:37
- Usar un literal de cadena de C++ significa que no necesitamos llamar a
strlen
para calcular la longitud. El compilador ya lo sabe. - Podría permitir implementaciones de bibliotecas donde los datos de cadena apuntan a la memoria en el espacio global, utilizando literales de C siempre se debe forzar una copia de los datos para amontonar la memoria en la construcción.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-28 03:13:19