string - remove - strip_tags wordpress
¿Cuáles son las diferencias entre ''String'' y ''str'' de Rust? (6)
En palabras sencillas, String
es un tipo de datos almacenado en el montón (como Vec
), y usted tiene acceso a esa ubicación.
&str
es un tipo de segmento. Eso significa que es solo una referencia a una String
ya presente en algún lugar del montón.
&str
no hace ninguna asignación en tiempo de ejecución. Entonces, por razones de memoria, puedes usar &str
sobre String
. Pero, tenga en cuenta que al usar &str
puede que tenga que lidiar con &str
vida explícitos.
¿Por qué Rust tiene String
y str
? ¿Cuáles son las diferencias entre String
y str
? ¿Cuándo se usa String
lugar de str
y viceversa? ¿Uno de ellos está en desuso?
En realidad son completamente diferentes. En primer lugar, un str
no es más que una cosa de nivel de tipo; solo se puede razonar en el nivel de tipo porque se denomina tipo de tamaño dinámico (DST). El tamaño que toma el str
no se puede conocer en el momento de la compilación y depende de la información del tiempo de ejecución; no se puede almacenar en una variable porque el compilador debe saber en el momento de la compilación cuál es el tamaño de cada variable. Conceptualmente, una str
es solo una fila de u8
bytes con la garantía de que forma UTF-8 válido. ¿Qué tan grande es la fila? Nadie lo sabe hasta el tiempo de ejecución, por lo que no se puede almacenar en una variable.
Lo interesante es que a &str
o cualquier otro puntero a una str
como Box<str>
existe en el tiempo de ejecución. Este es un llamado "puntero de grasa"; es un puntero con información adicional (en este caso, el tamaño del objeto al que apunta), por lo que es el doble de grande. De hecho, a &str
está bastante cerca de una String
(pero no de a &String
). A &str
son dos palabras; un puntero a un primer byte de un str
y otro número que describe cuántos bytes de largo es el str
.
Contrariamente a lo que se dice, un str
no necesita ser inmutable. Si puede obtener una &mut str
como un puntero exclusivo a la str
, puede mutarla y todas las funciones seguras que la mutan garantizan que la restricción UTF-8 se mantiene porque si se infringe, entonces tenemos un comportamiento indefinido como la biblioteca asume. esta restricción es verdadera y no la busca.
Entonces, ¿qué es una String
? Son tres palabras; dos son los mismos que para &str
pero agrega una tercera palabra que es la capacidad del buffer de str
en el montón, siempre en el montón (un str
no está necesariamente en el montón) que administra antes de que se llene y tenga que reasignarse . la String
básicamente posee una str
como dicen; lo controla y puede redimensionarlo y reasignarlo cuando lo considere oportuno. Así que una String
es como se dice más cerca de a &str
que a str
.
Otra cosa es una Box<str>
; este también posee un str
y su representación en tiempo de ejecución es la misma que un &str
pero también posee el str
diferencia del &str
pero no puede redimensionarlo porque no conoce su capacidad, por lo que básicamente un Box<str>
puede verse como un fijo longitud String
que no se puede redimensionar (siempre puedes convertirla en una String
si quieres redimensionarla).
Existe una relación muy similar entre [T]
y Vec<T>
excepto que no hay una restricción UTF-8 y puede contener cualquier tipo cuyo tamaño no sea dinámico.
El uso de str
en el nivel de tipo es principalmente para crear abstracciones genéricas con &str
; existe en el nivel de tipo para poder escribir rasgos convenientemente. En teoría, str
como cosa de tipo no tenía que existir y only &str
pero eso significaría que se tendría que escribir una gran cantidad de código adicional que ahora puede ser genérico.
&str
es super útil para poder tener varias subcadenas diferentes de un String
sin tener que copiar; como se dice, una String
es propietaria de la str
en el montón que administra y si solo pudiera crear una subcadena de una String
con una nueva String
, tendría que copiarse porque todo en Rust solo puede tener un único propietario para lidiar con la seguridad de la memoria. Entonces, por ejemplo, puedes cortar una cadena:
let string: String = "a string".to_string();
let substring1: &str = &string[1..3];
let substring2: &str = &string[2..4];
Tenemos dos cadenas de subcadenas diferentes de la misma cadena. string
es la que posee el búfer completo de str
real en el montón y las subcadenas &str
son simplemente punteros a ese búfer en el montón.
Las cadenas son un vector de char, puedes acceder a ellas y modificarlas son inmutables.
Tengo antecedentes en C ++ y me pareció muy útil pensar en String
y &str
en términos de C ++:
- Un Rust
String
es como unstd::string
; es dueño de la memoria y hace el trabajo sucio de administrar la memoria. - Un Rust
&str
es como unchar*
(pero un poco más sofisticado); nos señala el comienzo de un fragmento de la misma manera que puede obtener un puntero a los contenidos destd::string
.
¿Alguno de ellos va a desaparecer? No lo creo. Sirven dos propósitos:
String
mantiene el búfer y es muy práctico de usar. &str
es liviano y debe usarse para "mirar" las cuerdas. Puede buscar, dividir, analizar e incluso reemplazar trozos sin necesidad de asignar nueva memoria.
&str
puede mirar dentro de una String
ya que puede apuntar a una cadena literal. El siguiente código debe copiar la cadena literal en la memoria administrada de la String
:
let a: String = "hello rust".into();
El siguiente código le permite usar el literal en sí mismo sin copia (aunque de solo lectura)
let a: &str = "hello rust";
String
es el tipo de cadena de montón dinámico, como Vec
: Vec
cuando necesite poseer o modificar sus datos de cadena.
str
es una secuencia inmutable 1 de UTF-8 bytes de longitud dinámica en algún lugar de la memoria. Dado que el tamaño es desconocido, solo se puede manejar detrás de un puntero. Esto significa que la mayoría de las veces 2 aparece como &str
: una referencia a algunos datos UTF-8, que normalmente se denomina "segmento de cadena" o simplemente "segmento". Una porción es solo una vista de algunos datos, y esos datos pueden estar en cualquier lugar, por ejemplo,
- en almacenamiento estático: una cadena literal
"foo"
es un&''static str
. Los datos están codificados en el archivo ejecutable y se cargan en la memoria cuando se ejecuta el programa. - dentro de un montón asignado
String
:String
desreferencias a una vista&str
de los datos delString
. en la pila: por ejemplo, lo siguiente crea una matriz de bytes asignada a la pila, y luego obtiene una vista de esos datos como
&str
:use std::str; let x: &[u8] = &[b''a'', b''b'', b''c'']; let stack_str: &str = str::from_utf8(x).unwrap();
En resumen, use String
si necesita datos de cadena propios (como pasar cadenas a otras tareas, o compilarlos en tiempo de ejecución), y use &str
si solo necesita una vista de una cadena.
Esto es idéntico a la relación entre un vector Vec<T>
y una división &[T]
, y es similar a la relación entre el valor por T
y la referencia por referencia &T
para los tipos generales.
1 A str
es longitud fija; no puede escribir bytes más allá del final, o dejar bytes finales no válidos. Dado que UTF-8 es una codificación de ancho variable, esto obliga a que todas las str
sean inmutables. En general, la mutación requiere escribir más o menos bytes de los que había antes (por ejemplo, reemplazar un a
(1 byte) con un ä
(2+ bytes) requeriría hacer más espacio en el str
).
2 En este momento solo puede aparecer como &str
, pero los tipos de tamaño dinámico pueden permitir cosas como Rc<str>
para una secuencia de referencia de UTF-8 bytes. También puede que no, str
no encaja perfectamente en el esquema DST, ya que no hay una versión de tamaño fijo (todavía).