Pour un projet personnel, j'ai implémenté ma propre libstdC++. Petit à petit, j'ai fait de beaux progrès. Habituellement, je vais utiliser des exemples de http://www.cplusplus.com/reference/ pour quelques cas de test de base pour m'assurer que j'ai la fonctionnalité évidente fonctionnant comme prévu.Ceci est illégal non?
Aujourd'hui, je suis tombé sur un problème avec std::basic_string::replace
, en particulier avec les versions à base iterator en utilisant l'exemple copié mot pour mot du site (http://www.cplusplus.com/reference/string/string/replace/) (J'ai ajouté un commentaire à indiquer les lignes en question):
// replacing in a string
#include <iostream>
#include <string>
using namespace std;
int main()
{
string base="this is a test string.";
string str2="n example";
string str3="sample phrase";
string str4="useful.";
// function versions used in the same order as described above:
// Using positions: *123456789*12345
string str=base; // "this is a test string."
str.replace(9,5,str2); // "this is an example string."
str.replace(19,6,str3,7,6); // "this is an example phrase."
str.replace(8,10,"just all",6); // "this is just a phrase."
str.replace(8,6,"a short"); // "this is a short phrase."
str.replace(22,1,3,'!'); // "this is a short phrase!!!"
// Using iterators: *123456789*
string::iterator it = str.begin(); //^
str.replace(it,str.end()-3,str3); // "sample phrase!!!"
// *** this next line and most that follow are illegal right? ***
str.replace(it,it+6,"replace it",7); // "replace phrase!!!"
it+=8; // ^
str.replace(it,it+6,"is cool"); // "replace is cool!!!"
str.replace(it+4,str.end()-4,4,'o'); // "replace is cooool!!!"
it+=3; // ^
str.replace(it,str.end(),str4.begin(),str4.end());
// "replace is useful."
cout << str << endl;
return 0;
}
Dans ma version de remplacer est mis en œuvre en termes d'une chaîne temporaire que je crée puis échanger avec *this
. Cela invalide clairement tous les itérateurs. Donc ai-je raison de dire que l'exemple est invalide? parce qu'il stocke les itérateurs, remplace-t-il et utilise à nouveau les itérateurs?
Ma copie de la norme (ISO 14882: 2003 - 21.3p5) dit:
Références, pointeurs et itérateurs se référant aux éléments d'une séquence basic_string peut être invalidée par ce qui suit utilise de cet objet basic_string:
- As an argument to non-member functions swap() (21.3.7.8), operator>>() (21.3.7.9), and getline() (21.3.7.9). - As an argument to basic_string::swap(). - Calling data() and c_str() member functions. - Calling non-const member functions, except operator[](), at(), begin(), rbegin(), end(), and rend(). - Subsequent to any of the above uses except the forms of insert() and erase() which return iterators, the first call to non-const member functions operator[](), at(), begin(), rbegin(), end(), or rend().
L'entrée sur les fonctions de membre non-const semble couvrir ce sujet. Donc, à moins que je manque quelque chose, alors ce code utilise des itérateurs invalidés non? Bien sûr, ce code fonctionne très bien avec libstdC++ de gcc, mais nous savons tous que cela ne prouve rien en ce qui concerne la conformité aux normes.
Ceci est en fait illégal, et j'en ai déjà informé le FBI. J'espère que vous avez un bon avocat. –
Ils auront besoin de construire plus de prisons, eep. –
Si vous vous interrogez à ce sujet - ne vous demandez pas. cplusplus.com est plein de bugs. –