bonjours à tous,
Dans le code ci-dessous, j'ai l'impression que la lvalue est copié au lieu d'etre déplacé car le pointeur ou se trouve la chaine de caractere "Salut" n'est plus la meme avant et apres le std::move
voici mon code :
std::string str = "Salut";
std::vector<std::string> v;
std::cout << "str.data() = " << (void*)str.data() << "; str.size() = " << str.size() << " ; str = " << str << std::endl;
//renvoie str.data() = 0x7ffcce8b6560; str.size() = 5 ; str = Salut
const char * pStr = str.data();
printf("myPrintf = %s\n", pStr); // renvoie Salut
v.push_back(std::move(str));
std::cout << "v[0].data() = " << (void*)v[0].data() << "; v[1] = " << v[1] << std::endl;
//renvoie v[1].data() = 0x562d71ada2e0; v[1] = Salut
pStr = str.data();//renvoie str.data() = 0x7ffcce8b6560; str.size() = 0 ; str =
printf("myPrintf = %s\n", pStr); //renvoie myPrintf =
On voit bien que str n'existe plus, mais n'a rien a été déplacé, il y a eu copie. Je comprend vraiment pas l'utilité des lvalue
Merci d'avance pour vos éclaircissements :)
# Erreur ?
Posté par Anthony Jaguenaud . Évalué à 2. Dernière modification le 14 janvier 2022 à 15:55.
Salut, je vais sans doute écrire des bêtises…
dans la dernière partie tu utilises
V[1]
alors qu’il n’y a que l’élément 0.Si a la place de ….data() tu utilises ….c_str() ? Ça change quelque chose ? (normalement non.)
Après, le move est fait pour éviter des grosses copies, ici on peut copier avec juste une copie de 64bits. Avec une très longue chaîne, c’est pareil ?
Le push_back doit également allouer la mémoire, si tu fait un vector.resize(8) avant le push_back, est-ce que ça se comporte pareil ?
Pas d’idée supplémentaire.
# attention,
Posté par fearan . Évalué à 3.
avec des string, tu va tomber sur la sso (short string optimisation), si ta chaîne est plus courte qu'un pointeur, il n'y a pas d'allocation dynamique; et donc ça va pointer sur l'objet lui même.
Il vaut mieux tester avec une chaîne de plus de 64 octets.
Ensuite comme dit plus haut tu va taper la case 1 du vecteur, qui n'a qu'un seul élément tu risque le segfault
Il ne faut pas décorner les boeufs avant d'avoir semé le vent
[^] # Re: attention,
Posté par Zenitram (site web personnel) . Évalué à 3.
plus de 22 suffira.
Sur machine 64-bit : 8 octets par champs * 3 champs (début, taille, fin/taille allouée) - le 0 terminal - 1 octet pour la taille en cas de SSO.
# SSO Optimisation
Posté par moi1392 . Évalué à 2.
Depuis le passage à C++11 (si je ne dis pas de bêtises) et le cassage d'ABI qui va avec, la norme impose aux std::string l'optimisation SSO (Small String Optimisation),
En gros, l'implémentation "classique" du stockage de l'information dans une std::string ressemble fortement à celle d'un std::vector, un pointer pour le début, un pour la fin de la string et un pour la fin de la zone allouée.
ça fait donc 3 pointeurs, et en 64 bits, 24 octets donc.
Du coup au lieu d'allouer de l'espace mémoire pour les petites strings (moins de 23 octet pour garder le 0 terminal), on peut simplement se servir de ces 24 octets pour mettre la donnée "directement"
Pour ces petites string le temps de la copie est négligeable par rapport au temps d'allocation et en particulier c'est thread-safe par rapport à un std::move.
Voila pourquoi SSO est maintenant le standard pour les std::string.
PS: l'implémentation est un peu plus compliquée que cela, du coup c'est un peu moins de 23 octets, tu peux essayer de faire des tests pour voir à partir de quand le comportement change.
# tout marche
Posté par cosmoff . Évalué à 2.
oui j'ai augmenté la taille du string et le systeme de rvalue a bien donné l'adresse ou se trouve la chaine de caractere, et n'a donc pas fait de copy
merci beaucoup pour vos éclaircissements
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.