¿Por qué tiene Rust Stringy str? ¿Cuáles son las diferencias entre Stringy str? ¿Cuándo se usa uno en Stringlugar de stry viceversa? ¿Uno de ellos está en desuso?
Stringes el tipo de cadena dinámico dinámico, como Vec: utilícelo cuando necesite poseer o modificar sus datos de cadena.
stres una secuencia inmutable de 1 UTF-8 bytes de longitud dinámica en algún lugar de la memoria. Como el tamaño es desconocido, solo se puede manejar detrás de un puntero. Esto significa que strmás comúnmente 2 aparece como &str: una referencia a algunos datos UTF-8, normalmente llamados "corte de cadena" o simplemente un "corte". Un segmento es solo una vista de algunos datos, y esos datos pueden estar en cualquier lugar, por ejemplo
"foo"es a &'static str. Los datos se codifican en el ejecutable y se cargan en la memoria cuando se ejecuta el programa.String : Stringdesreferencias a una &strvista de los Stringdatos del 's.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, úselo Stringsi necesita datos de cadena propios (como pasar cadenas a otros hilos o construirlos en tiempo de ejecución), y úselo &strsi solo necesita una vista de una cadena.
Esto es idéntico a la relación entre un vector Vec<T>y un corte &[T], y es similar a la relación entre el valor Ty la referencia &Tpara los tipos generales.
1 A stres de longitud fija; no puede escribir bytes más allá del final, ni dejar bytes finales inválidos. Como UTF-8 es una codificación de ancho variable, esto obliga a todos los strs a ser inmutables en muchos casos. En general, la mutación requiere escribir más o menos bytes que antes (por ejemplo, reemplazar un a(1 byte) con un ä(2+ bytes) requeriría hacer más espacio en el str). Existen métodos específicos que pueden modificar un &strlugar, principalmente aquellos que manejan solo caracteres ASCII, como make_ascii_uppercase.
2 Los  tipos de tamaño dinámico permiten cosas como Rc<str>una secuencia de bytes UTF-8 contados de referencia desde Rust 1.2. Rust 1.21 permite crear fácilmente estos tipos.
&strestá formado por dos componentes: un puntero a algunos bytes y una longitud".[u8; N].Rc<str>yArc<str>ahora se pueden usar a través de la biblioteca estándar.Tengo experiencia en C ++ y me pareció muy útil pensar
Stringy&stren términos de C ++:Stringes como unstd::string; posee la memoria y hace el trabajo sucio de administrar la memoria.&stres como unchar*(pero un poco más sofisticado); nos señala el comienzo de un fragmento de la misma manera en que puede obtener un puntero al contenido destd::string.¿Alguno de ellos va a desaparecer? No lo creo. Tienen dos propósitos:
Stringmantiene el búfer y es muy práctico de usar.&stres liviano y debe usarse para "mirar" en cuerdas. Puede buscar, dividir, analizar e incluso reemplazar fragmentos sin necesidad de asignar nueva memoria.&strpuede mirar dentro de una,Stringya que puede apuntar a una cadena literal. El siguiente código debe copiar la cadena literal en laStringmemoria administrada:El siguiente código le permite usar el literal en sí mismo sin copia (aunque solo lectura)
fuente
str, solo se usa como&str, es un segmento de cadena, una referencia a una matriz de bytes UTF-8.Stringes lo que solía ser~str, una matriz de bytes UTF-8 que se puede crecer y poseer.fuente
~strahora esBox<str>~strera cultivable mientrasBox<str>que no es cultivable. (Eso~stry~[T]fueron mágicamente cultivables, a diferencia de cualquier otro objeto~, fue exactamente por quéStringyVec<T>se introdujeron, de modo que las reglas fueron directas y consistentes.)En realidad son completamente diferentes. En primer lugar, a
strno es más que una cosa de nivel de tipo; solo se puede razonar a nivel de tipo porque es un tipo denominado de tamaño dinámico (DST). El tamaño questrocupa no se puede conocer en tiempo de compilación y depende de la información de tiempo de ejecución; no se puede almacenar en una variable porque el compilador necesita saber en tiempo de compilación cuál es el tamaño de cada variable. Astres conceptualmente solo una fila deu8bytes con la garantía de que forma un UTF-8 válido. ¿Qué tan grande es la fila? Nadie lo sabe hasta el tiempo de ejecución, por lo tanto, no se puede almacenar en una variable.Lo interesante es que una
&stro cualquier otro puntero a unastrcomoBox<str>lo hace existir en tiempo de ejecución. Este es un llamado "indicador gordo"; es un puntero con información adicional (en este caso, el tamaño de la cosa a la que apunta), por lo que es el doble de grande. De hecho, a&strestá bastante cerca de aString(pero no a&String). A&strson dos palabras; un puntero al primer byte de aystrotro número que describe cuántos bytes tiene la longitud delstr.Contrariamente a lo que se dice, a
strno necesita ser inmutable. Si puede obtener un&mut strcomo puntero exclusivo para elstr, puede mutarlo y todas las funciones seguras que lo mutan garantizan que la restricción UTF-8 se mantenga porque si se viola, entonces tenemos un comportamiento indefinido ya que la biblioteca asume que esta restricción es cierto y no lo comprueba.Entonces, ¿qué es un
String? Eso son tres palabras; dos son los mismos que para&strpero agrega una tercera palabra que es la capacidad delstrbúfer en el montón, siempre en el montón (astrno está necesariamente en el montón) que administra antes de que se llene y tenga que reasignarse. elStringbásicamente posee unastrcomo dicen; lo controla y puede cambiar su tamaño y reasignarlo cuando lo considere conveniente. Entonces aStringes como se dice más cerca de a&strque a astr.Otra cosa es una
Box<str>; esto también posee astry su representación en tiempo de ejecución es la misma que a&strpero también posee lastrdiferencia,&strpero no puede cambiar su tamaño porque no conoce su capacidad, por lo que básicamenteBox<str>se puede ver como una longitud fijaStringque no se puede cambiar de tamaño (puede siempre conviértalo en unStringsi desea cambiar su tamaño).Existe una relación muy similar entre
[T]yVec<T>excepto que no hay restricción UTF-8 y puede contener cualquier tipo cuyo tamaño no sea dinámico.El uso de
stren 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,strcomo una cosa tipo no necesitaba existir y solo&streso significaría que se tendría que escribir una gran cantidad de código adicional que ahora puede ser genérico.&stres súper útil para poder tener múltiples subcadenas diferentes de aStringsin tener que copiar; como se dijo,Stringposee elstren el montón que administra y si solo pudiera crear una subcadena de aStringcon un nuevoString, tendría que copiarlo porque todo en Rust solo puede tener un único propietario para lidiar con la seguridad de la memoria. Entonces, por ejemplo, puede cortar una cadena:Tenemos dos subcadenas diferentes
strde la misma cadena.stringes el propietario delstrbúfer completo real en el montón y las&strsubcadenas son solo punteros gordos a ese búfer en el montón.fuente
std::Stringes simplemente un vector deu8. Puede encontrar su definición en el código fuente . Está asignado al montón y puede crecer.stres un tipo primitivo, también llamado corte de cadena . Un corte de cadena tiene un tamaño fijo. Una cadena literal comolet test = "hello world"tiene&'static strtipo.testes una referencia a esta cadena asignada estáticamente.&strno se puede modificar, por ejemplo,strtiene una porción mutable&mut str, por ejemplo:pub fn split_at_mut(&mut self, mid: usize) -> (&mut str, &mut str)Pero un pequeño cambio en UTF-8 puede cambiar la longitud de su byte, y un segmento no puede reasignar su referente.
fuente
En palabras sencillas, el
Stringtipo de datos se almacena en el montón (al igual queVec) y tiene acceso a esa ubicación.&strEs un tipo de corte. Eso significa que es solo referencia a un ya presenteStringen algún lugar del montón.&strno hace ninguna asignación en tiempo de ejecución. Entonces, por razones de memoria, puede usar&strmásString. Pero tenga en cuenta que al usarlo&strpuede tener que lidiar con vidas explícitas.fuente
stres queviewya está presenteStringen el montón.Para personas de C # y Java:
String===StringBuilder&strCadena de óxido === (inmutable)Me gusta pensar en a
&strcomo una vista en una cadena, como una cadena interna en Java / C # donde no puede cambiarla, solo cree una nueva.fuente
Aquí hay una explicación rápida y fácil.
String- Una estructura de datos atribuible a almacenamiento dinámico que se puede crecer. Se puede obligar a a&str.str- es (ahora, a medida que Rust evoluciona) una cadena mutable de longitud fija que vive en el montón o en el binario. Solo puede interactuar construn tipo prestado a través de una vista de corte de cadena, como&str.Consideraciones de uso:
Prefiera
Stringsi desea poseer o mutar una cadena, como pasar la cadena a otro hilo, etc.Prefiere
&strsi quieres tener una vista de solo lectura de una cadena.fuente