2017-09-10 3 views
1

Je continue d'obtenir cette erreur de segment mais je n'ai aucune idée d'où elle vient. Désolé, je suis encore nouveau pour le codage.Erreur de segmentation dans la fonction récursive, stockage du résultat dans un vecteur

#include <iostream> 
#include <vector> 

using namespace std; 

vector<int> map(vector<int> v, vector<int>::iterator i, vector<int> result) { //set i = v.begin() in main 
    if (i==v.end()) { 
     return result; 
    } else { 
     result.push_back((*i)*(*i)); 
     i++; 
     map(v,i,result); 
    } 
} 

int main() { 
    vector<int> v; 
    vector<int> result; 

    for (int i=0;i<20;i++) { 
     v.push_back(i); 
    } 

    vector<int>::iterator it=v.begin(); 

    result=map(v,it,result); 
} 

Et apparemment, je dois ajouter plus de mot parce que ma question est principalement du code.

+0

Sur quelle ligne est le défaut? –

+2

Passez votre vecteur par référence, pas par valeur. – PaulMcKenzie

Répondre

2

Vous passez le vecteur par valeur, ainsi les modifications ne persistent pas parmi les appels de fonction.

Passez le vecteur par référence pour y parvenir.

De plus, vous devez également renvoyer le vecteur dans le cas else.

En outre, passez v par référence aussi, afin que l'itérateur soit OK lorsque vous vérifiez v.end(). Sinon, il recherchera une copie différente de v à chaque appel de fonction.

Mettre tout ensemble, vous obtenez:

vector<int> map(vector<int>& v, vector<int>::iterator i, vector<int>& result) { 
    if (i==v.end()) { 
     return result; 
    } else { 
     result.push_back((*i)*(*i)); 
     i++; 
     return map(v,i,result); 
    } 
} 
+0

@xaxxon mis à jour, que pensez-vous maintenant? Oh, je vois que vous avez posté une réponse aussi, va vérifier dans un moment (vous verrez mon upvote si je l'aime). – gsamaras

0

Le problème est presque certainement parce que vous ne retournez pas une valeur de votre fonction récursive dans de nombreuses situations:

vector<int> map(vector<int> v, vector<int>::iterator i, vector<int> result) { //set i = v.begin() in main 
    if (i==v.end()) { 
     return result; 
    } else { 
     result.push_back((*i)*(*i)); 
     i++; 
     map(v,i,result); 
     /** NO RETURN VALUE HERE **/ 
    } 
} 

Au lieu de cela, faire la dernière ligne être:

return map(v,i,result); 

Idéalement, vous ne passerez pas de vecteurs en valeur, mais cela ne provoquera pas le crash de votre programme, il vous suffit de courir plus lentement.

1

Il y a deux problèmes:

Puisque vous passez le premier paramètre (std::vector) en valeur, chaque appel à map utilise un vecteur différent de l'original. Ainsi, l'itérateur que vous passez n'est pas compatible avec le vecteur transmis et votre programme affichera un comportement indéfini.

Pour résoudre ce problème, transmettez le std::vector par référence, et non par valeur. Puisque vous aussi ne pas changer la vector au sein de la fonction, passer par const référence:

vector<int> map(const vector<int>& v, vector<int>::iterator i, vector<int> result) 

Maintenant, le iterator est itérer sur le vecteur réel qui a été transmis, pas une copie temporaire du vecteur.

Le deuxième problème est que vous ne renvoyez pas de valeur à partir de la fonction map. Ne pas renvoyer une valeur d'une fonction supposée renvoyer une valeur est un comportement indéfini.

Pour résoudre le problème, supprimez l'instruction else (pour éviter les avertissements du compilateur) et renvoie la valeur de la fonction:

vector<int> map(const vector<int>& v, vector<int>::iterator i, vector<int> result) 
{ 
    if (i == v.end()) 
     return result; 
    result.push_back((*i)*(*i)); 
    i++; 
    return map(v, i, result); 
} 
0

Une cause potentielle d'un accident sera parce que l'appel récursif n'est pas suivi par (ou une partie de) une déclaration de retour. Lorsque l'appelant accède à la valeur de retour, le résultat est un comportement indéfini.

Même en ignorant cela, les arguments sont passés par valeur.Toute modification apportée au vecteur ne sera donc pas visible pour l'appelant. Plus significativement, le test i == v.end() aura également un comportement indéfini (une autre cause potentielle d'accident) car i et v.end() ne sont pas des itérateurs obtenus du même conteneur (i est un itérateur du vecteur dans main(), et v est une copie de ce vecteur - qui a un ensemble complètement différent d'itérateurs).

Enfin, std::map est un type de modèle dans la bibliothèque standard. Avoir une fonction nommée map() - en particulier quand un using namespace std est en jeu, est susceptible de confondre les programmeurs, sinon d'entraîner une ambiguïté pour le compilateur.