2010-02-09 22 views
-3

regarder le code simple suivant:Pourquoi les opérations string :: append se comportent-elles étrangement?

#include <iostream> 
#include <string> 
using namespace std; 

int main() 
{ 
    string s("1234567890"); 
    string::iterator i1 = s.begin(); 
    string::iterator i2 = s.begin(); 
    string s1, s2; 
    s1.append(i1, ++i1); 
    s2.append(++i2, s.end()); 

    cout << s1 << endl; 
    cout << s2 << endl; 
} 

ce que vous attendez-vous que la sortie soit?

voulez-vous, comme moi, attendent que ce soit:

1 
234567890 

mal! est:

234567890 

à-dire la première chaîne est vide. Les coutures qui préfixent l'opérateur d'incrémentation posent problème avec les itérateurs. ou ai-je oublié quelque chose?

+7

I Je ne suis pas l'un des downvoters ici, mais je suggère qu'ils découlent de votre suggestion que vous avez trouvé un bug de compilateur. Tout le monde a un "Ai-je trouvé un bug dans ?" moment tôt (dans mon cas c'était libm), et ils ont tous tort. Si vous trouvez tous un bug dans quelque chose qui est fortement utilisé, ce sera après avoir beaucoup d'expérience avec l'outil en question. – dmckee

+2

Pourquoi les downvotes? Est-ce que SO est plein de développeurs GCC qui se sont sentis personnellement fait allusion? (Je veux dire les développeurs * de * GCC) – Manuel

+2

@Manuel: downvoting en raison de la façon dont la question a été posée. Voir http://catb.org/~esr/faqs/smart-questions.html # id382249. Même si cela avait été un bug, ce n'est pas le bon forum pour les rapports de bugs. Et le titre est inutilement générique. Au moins, il y avait une bonne recette de repro. – user9876

Répondre

3

Pas un bug.

L'ordre dans lequel les arguments de

s1.append(i1, ++i1); 

sont évalués ne sont pas spécifiées par la norme. Le compilateur est libre d'utiliser n'importe quel ordre qu'il choisit. Dans ce cas, il évalue le deuxième argument (++i1) avant le premier (i1) et vous spécifiez une plage null à copier.

8

Les implémentations C++ sont libres d'évaluer les arguments dans n'importe quel ordre. Dans ce cas, si ++ i1 est évalué en premier, vous obtiendrez une chaîne vide.

3

La norme C++ ne spécifie rien concernant l'ordre dans lequel les arguments de la fonction sont évalués, ce qui la rend dépendante de l'implémentation. C++ exige que les arguments d'une fonction soient complètement évalués (et tous les effets secondaires affichés) avant d'entrer dans la fonction, mais l'implémentation est libre d'évaluer les arguments dans n'importe quel ordre. les paramètres mêmes, résultant en une chaîne vide.

Plus d'informations sur ce comportement ici comp.compilers newsgroup

14

Il vous manque quelque chose: cela n'a vraiment rien à voir avec les itérateurs. L'ordre dans lequel les arguments d'une fonction sont évalués n'est pas spécifié. En tant que tel votre: append(i1, ++i1); dépendrait d'un comportement non spécifié, quel que soit le type de i1. Juste par exemple, donné quelque chose beaucoup plus simple comme:

void print(int a, int b) { 
    std::cout << a << " " << b << "\n"; 
} 

int main() { 
    int a =0; 
    print(a, ++a); 
    return 0; 
} 

Votre sortie pourrait parfaitement être raisonnablement « 0 1 » vous semblez attendre, mais il pourrait aussi parfaitement raisonnablement: « 1 1 ». Puisque ceci n'est pas spécifié, il peut changer d'une version du compilateur à l'autre, ou même avec le même compilateur quand vous changez de drapeaux, ou (en théorie) pourrait varier selon la phase de la lune ...