Quelles sont les différences entre `String` et `str ' de Rust?

Pourquoi ne Rouille String et str? Quelles sont les différences entre String et str? Quand utilise-t-on String au lieu de str et vice versa? Est l'un d'eux se soit obsolète?

205
demandé sur maxcountryman 2014-06-11 12:29:34

6 réponses

String est le type de chaîne de tas dynamique, comme Vec: Utilisez-le lorsque vous devez posséder ou modifier vos données de chaîne.

str est immuable1 séquence d'octets UTF-8 de longueur dynamiques quelque part dans la mémoire. Puisque la taille est inconnue, on ne peut gérer que derrière un pointeur. Cela signifie que str le plus souvent2 apparaît comme &str: une référence à certaines données UTF-8, normalement appelées "tranche de chaîne" ou simplement "tranche". une tranche est juste une vue sur certaines données, et ces données peuvent être n'importe où, par exemple

  • dans le stockage statique: un littéral de chaîne "foo" est un &'static str. Les données sont codées en dur dans l'exécutable et chargées en mémoire lorsque le programme s'exécute.
  • dans un tas alloué String: String déréférences à une vue &str des données de String.
  • Sur la pile: par exemple, ce qui suit crée un tableau d'octets alloué à la pile, puis obtient une vue de ces données en tant que &str:

    use std::str;
    
    let x: &[u8] = &[b'a', b'b', b'c'];
    let stack_str: &str = str::from_utf8(x).unwrap();
    

Dans résumé, utilisez String si vous avez besoin de données de chaîne possédées (comme passer des chaînes à d'autres tâches, ou les construire à l'exécution), et utilisez &str Si vous avez seulement besoin d'une vue d'une chaîne.

Ceci est identique à la relation entre un vecteur Vec<T> et une tranche &[T], et est semblable à la relation entre la valeur T et par référence &T pour les types généraux.


1 un str est de longueur fixe; vous ne pouvez pas écrire d'octets au-delà de la fin ou laisser des octets non valides. Puisque UTF-8 est un codage à largeur variable, cela force efficacement tous les str s à être immuables. En général, la mutation nécessite d'écrire plus ou moins d'octets qu'auparavant (par exemple, remplacer un a (1 octet) par un ä (2 + octets) nécessiterait de faire plus de place dans le str).

2 pour le moment, il ne peut que apparaître comme &str, mais les types de taille dynamique peuvent permettre des choses comme Rc<str> pour une séquence D'octets UTF-8 comptés par référence. Il peut également ne pas, str ne correspond pas parfaitement au schéma DST, car il n'y a pas encore de version de taille fixe.

242
répondu huon 2018-05-17 21:10:35

J'ai un fond C++ et j'ai trouvé très utile de penser à String et &str en termes C++:

  • une rouille {[2] } est comme un std::string; elle possède la mémoire et fait le sale travail de gestion de la mémoire.
  • Rouille &str, c'est comme un char* (mais un peu plus sophistiqué); il nous montre le début d'un morceau de la même façon vous pouvez obtenir un pointeur vers le contenu de std::string.

L'un d'eux va-t-il disparaître? Je ne le crois pas. Elles servent à deux objectifs:

String conserve le tampon et est très pratique à utiliser. &str est léger et devrait être utilisé pour "regarder" dans les cordes. Vous pouvez rechercher, diviser, analyser et même remplacer des morceaux sans avoir besoin d'allouer de nouvelle mémoire.

&str pouvez regarder à l'intérieur d'un String comme il peut pointer vers une chaîne littérale. Le code suivant doit copier la chaîne littérale dans la mémoire gérée String:

let a: String = "hello rust".into();

Le code suivant vous permet d'utiliser le littéral lui-même sans copie (lecture seule bien que)

let a: &str = "hello rust";
33
répondu Luis Ayuso 2017-06-07 14:24:06

str, seulement utilisé comme &str, est une tranche de chaîne, une référence à un tableau d'octets UTF-8.

String est ce qui était ~str, Un tableau d'octets UTF-8 cultivable et possédé.

31
répondu Chris Morgan 2015-02-21 10:31:22

Ils sont en fait complètement différents. Tout d'abord, un str n'est rien d'autre qu'une chose au niveau du type; il ne peut être raisonné qu'au niveau du type car c'est un type dit de taille dynamique (DST). La taille que prend str ne peut pas être connue au moment de la compilation et dépend des informations d'exécution - elle ne peut pas être stockée dans une variable car le compilateur doit savoir au moment de la compilation Quelle est la taille de chaque variable. Un str est conceptuellement juste une ligne de u8 octets, avec la garantie qu'il formulaires UTF-8 valides. Quelle est la taille de la rangée? Personne ne sait jusqu'à l'exécution, donc il ne peut pas être stocké dans une variable.

La chose intéressante est qu'un &str ou tout autre pointeur vers un str comme Box<str> existe-t-il au moment de l'exécution. C'est un soi-disant "pointeur fat"; c'est un pointeur avec des informations supplémentaires (dans ce cas la taille de la chose qu'il pointe) donc c'est deux fois plus grand. En fait, un &str est assez proche d'un String (mais pas à un &String). Un &str est deux mots; un pointeur à l' premier octet d'un str et un autre nombre qui décrit combien d'octets de long le str est.

, Contrairement à ce qui est dit, un str n'a pas besoin d'être immuable. Si vous pouvez obtenir un &mut str en tant que pointeur exclusif sur le str, vous pouvez le muter et toutes les fonctions sûres qui le mutent garantissent que la contrainte UTF-8 est maintenue car si cela est violé, nous avons un comportement indéfini car la bibliothèque suppose que cette contrainte est vraie et ne la vérifie pas.

Alors qu'est-ce qui est un String? C'est trois mots; deux sont les mêmes que pour &str, mais il ajoute un troisième mot qui est la capacité de la str tampon sur le tas, toujours sur le tas (un str n'est pas nécessairement sur le tas), il gère avant d'être rempli et doit ré-allouer. le String fondamentalement possède un str, comme ils disent; il contrôle et pouvez la redimensionner et la réaffecter elle lorsqu'elle le juge opportun. Donc un String est comme dit plus proche d'un &str que de str.

Une autre chose est un Box<str>; cela aussi possède un str et sa représentation d'exécution est la même qu'un &str mais il possède également le str contrairement au &str mais il ne peut pas le redimensionner car il ne connaît pas sa capacité donc fondamentalement un Box<str> peut être considéré comme un String de longueur fixe qui ne peut pas être redimensionné (vous pouvez toujours le convertir en String Si vous voulez le redimensionner).

Une relation très similaire existe entre [T] et Vec<T> sauf qu'il n'y a pas de contrainte UTF-8 et qu'elle peut contenir n'importe quel type dont la taille n'est pas dynamique.

Le l'utilisation de str au niveau du type consiste principalement à créer des abstractions génériques avec &str; Il existe au niveau du type pour pouvoir écrire commodément des traits. En théorie str comme une chose de type n'avait pas besoin d'exister et seulement &str mais cela signifierait que beaucoup de code supplémentaire devrait être écrit qui peut maintenant être générique.

&str c'est super utile de pouvoir avoir plusieurs sous-chaînes d'une String sans avoir à copier; comme l'a dit un String propriétaire de le str sur le tas qu'il gère et si vous ne pouviez créer qu'une sous-chaîne d'un String avec un nouveau String, Il faudrait le copier car tout dans Rust ne peut avoir qu'un seul propriétaire pour gérer la sécurité de la mémoire. Ainsi, par exemple, vous pouvez découper une chaîne:

let string: String   = "a string".to_string();
let substring1: &str = &string[1..3];
let substring2: &str = &string[2..4];

Nous avons deux sous-chaînes différentes str de la même chaîne. string est celui qui possède le tampon str complet réel sur le tas et les sous-chaînes &str ne sont que des pointeurs gras vers ce tampon sur le tas.

1
répondu Zorf 2018-07-27 20:29:25

En termes simples, String est le type de données stocké sur le tas comme Vec et vous avez accès au pointeur vers cet emplacement.

&str est un type de tranche. Cela signifie que c'est juste une référence à String déjà présent quelque part dans le tas.

&str ne fait aucune allocation à l'exécution. Donc, pour des raisons de mémoire, vous pouvez utiliser &str sur String. Mais, gardez à l'esprit que lorsque vous utilisez &str, vous devrez peut-être faire face à des durées de vie explicites.

0
répondu 00imvj00 2018-04-19 17:15:17

Chaîne sont un vecteur de char, vous pouvez y accéder et modifier str sont immuables

-1
répondu CrisMon_01 2018-10-05 13:56:30