2010-07-01 12 views
11

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.

+13

Ceci est en fait illégal, et j'en ai déjà informé le FBI. J'espère que vous avez un bon avocat. –

+0

Ils auront besoin de construire plus de prisons, eep. –

+1

Si vous vous interrogez à ce sujet - ne vous demandez pas. cplusplus.com est plein de bugs. –

Répondre

2

Cela semblera fonctionner si replace fonctionne sur place. Je ne pense pas que cela doive être appliqué de cette façon. Alors oui, je dirais que votre code est techniquement illégal.