IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Questions en vrac: librairie std,objet cout.


Sujet :

C++

  1. #41
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    C++0x était la version temporaire qui s'est finalement figée pour devenir C++11.
    Sinon, oui, un makefile ou équivalent (j'aime beaucoup CMake, qui est plus haut niveau qu'un makefile, et te permet de porter ton code vers d'autres environnements de compilation (visual studio, par exemple)), c'est vite indispensable.

    vector ne désigne ni une classe ni un type (toute classe est un type, mais certains types ne sont pas des classes, int par exemple). vector est un template, un modèle, à partir duquel le compilateur peut à la demande générer des classes ou des types. vector<int> est une classe (et donc un type), vector<string> est aussi une autre classe, différente de la première.

    Une instance de vector<int> est un objet.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  2. #42
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2011
    Messages
    104
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2011
    Messages : 104
    Points : 23
    Points
    23
    Par défaut
    Merci. Et structure alors ? . On définit un nouveau type/une nouvelle classe (sans méthode)

  3. #43
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2011
    Messages
    104
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2011
    Messages : 104
    Points : 23
    Points
    23
    Par défaut segmentation fault
    17)Je viens d'avoir por la premiere fois une erreur d'execution (et pas de compilation): segmentation fault . ??? Qu est ce que c'est? Voici mon code qui ne me parait pas faux (ps: si une âme charitable peut également me donner des astuces pour coder plus proprement, je suis scrupuleusement un livre sans savoir si la manière de coder est corecte, pour le moment je laisse le using namespace std et je sais que c'est pas bien mais c'est la seule erreur délibéré que je fais pour gagner du temps)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    #include <iostream>	
    #include <vector>
    #include <string>
    using namespace std;
     
    struct QCM{
    	string question;//Chaine de caratere
    	vector<string> reponses; //Tableau de chaine de caratère
    	unsigned int solution;
    };//attention au ";"
     
    typedef vector<QCM> Examen;//On doit ajoutr cette ligne après avoir créer la struture
     
    void affiche(const QCM& variableQcm);
    unsigned int poser_question(const QCM& varQCM);
    unsigned int demander_nombre(unsigned int a, unsigned int b);
    Examen creer_examen();//
     
     
     
     
    int main()
    {
    	Examen exam=creer_examen();
    	poser_question(exam[0]);
    	poser_question(exam[1]);
     
    	return 0;
    }
     
    Examen creer_examen(){
     
    	Examen varExam;
    	QCM qcm1;//Déclaration de la variable qcm de type/structure QCM
    	//Définition de la variable qcm de type/structure QCM
    	qcm1.question="Combien...adulte";//Initialisation des champs
    	qcm1.reponses={"32","beaucoup","aucunes"};
    	qcm1.solution=1;
     
    	QCM qcm2={{"Qui pose stupid question"},{"prof","toi","personne"},2};	
    		//poser_question(qcm);
     
    	return varExam;
    }
     
    void affiche(const QCM& variableQcm){
    //On affiche les questions et réponsesproposées
    	cout<<variableQcm.question<<endl;
     
    //Pour les questions proposées il faut parcourir/afficher un tableau de string (donc utilisation d'une boucle for)
    	for(size_t i(0);i<variableQcm.reponses.size();i++){//qcm.reponse est le champ reponse de la variable qcm
    	cout<<i+1<<" ";
    	cout<<variableQcm.reponses[i]<<endl; //Accès aux éléments d'un champ d'une structure
    	}
    }	
     
    unsigned int poser_question(const QCM& q)
    {
      affiche(q);
      return demander_nombre(1, q.reponses.size());//entre 1 et la taille du qcm
    }
     
     
    unsigned int demander_nombre(unsigned int a, unsigned int b)
    {
      /* échange les arguments s'ils n'ont pas été donnés dans *
       * le bon sens.                                          */
      if (a > b) { unsigned int tmp(b); b=a; a=tmp; }
     
      unsigned int res;
      do {
        cout << "Entrez un nombre entier compris entre "
             << a << " et " << b <<" : ";
        cin >> res;
      } while ((res < a) or (res > b));
     
      return res;
    }
    PS: sur codeblock:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    ||=== Build: Debug in monp (compiler: GNU GCC Compiler) ===|
    /home/laurent/monp/main.cpp||In function ‘Examen creer_examen()’:|
    /home/laurent/monp/main.cpp|37|warning: extended initializer lists only available with -std=c++11 or -std=gnu++11 [enabled by default]|
    /home/laurent/monp/main.cpp|37|warning: extended initializer lists only available with -std=c++11 or -std=gnu++11 [enabled by default]|
    /home/laurent/monp/main.cpp|37|error: no match foroperator=’ (operand types are ‘std::vector<std::basic_string<char> >’ and ‘<brace-enclosed initializer list>’)|
    /home/laurent/monp/main.cpp|37|note: candidate is:|
    /usr/include/c++/4.8/bits/vector.tcc|160|note: std::vector<_Tp, _Alloc>& std::vector<_Tp, _Alloc>::operator=(const std::vector<_Tp, _Alloc>&) [with _Tp = std::basic_string<char>; _Alloc = std::allocator<std::basic_string<char> >]|
    /usr/include/c++/4.8/bits/vector.tcc|160|note:   no known conversion for argument 1 from ‘<brace-enclosed initializer list>’ to ‘const std::vector<std::basic_string<char> >&’|
    /home/laurent/monp/main.cpp|40|warning: extended initializer lists only available with -std=c++11 or -std=gnu++11 [enabled by default]|
    /home/laurent/monp/main.cpp|40|warning: extended initializer lists only available with -std=c++11 or -std=gnu++11 [enabled by default]|
    /home/laurent/monp/main.cpp|40|error: could not convert ‘{"prof", "toi", "personne"}’ from ‘<brace-enclosed initializer list>’ to ‘std::vector<std::basic_string<char> >’|
    ||=== Build failed: 2 error(s), 4 warning(s) (0 minute(s), 0 second(s)) ===|

  4. #44
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Une structure et une classe, c'est la même chose. La seule différence, c'est que par défaut, tout est public dans une structure, alors que tout est privé dans une classe.

    Sinon, pour ton erreur, tu crées 2 QCM, mais jamais tu ne les ajoutes dans ton vecteur... Donc par la suite, quand tu accèdes à exam[0], tu accèdes à une zone mémoire à laquelle tu n'as pas droit, d'où le segmentation fault (c'est grosso modo ça que ça signifie).

    Sinon, ton compilateur a probablement un mode de compilation où ce genre d'erreurs va être indiqué plus clairement. Vu que tu utilises gcc: https://gcc.gnu.org/onlinedocs/libst...ebug_mode.html et en particulier ajouter -D_GLIBCXX_DEBUG sur la ligne de commande.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  5. #45
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2011
    Messages
    104
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2011
    Messages : 104
    Points : 23
    Points
    23
    Par défaut
    Merci!! Effectivement faut idiote que je n'arrivais pas à detecter.
    J'ai essayé d'jouter l'option mais malheureusement ça compile bien (sans detecter ce qui crée l' erreur segmentation fault!)

    rien à voir mais qu'estce qu'un container ?

  6. #46
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    L'option ne va pas empêcher de compiler, mais devrait remplacer à l'exécution le message "segmentation fault" par un message plus précis, comme "tentative d'accéder à la case numéro 0 d'un vector de taille 0", ce qui rend le debogage plus simple.

    Un conteneur est une classe dont le rôle est de contenir des instances d'autres classes, en nombre variable. std::vector<int> est un conteneur d'entiers. std::list<int> aussi.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  7. #47
    Membre émérite
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Points : 2 799
    Points
    2 799
    Par défaut
    snip : penser à regarder la deuxième page avent de répondre, réponse déjà donnée par Loïc

  8. #48
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2011
    Messages
    104
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2011
    Messages : 104
    Points : 23
    Points
    23
    Par défaut Pointeurs
    Bonjour,

    J'ai voulu tester certaines commandes pour comprendre les pointeurs:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    #include <iostream>	
    #include <string>	
     
    using namespace std;
     
     
    int main()
    {
     
    //1) Déclaration d'un pointeur sans initialisation (dangereux)
     
     
    /*	 int *pointeur1;// On déclare un pointeur (pointant sur une case allouée à un espace réservé aux entiers (int)) qui pointe sur n'importe quelle case donnée aléatoirement par le processeur. C'est dangereux car ce pointeur peut pointer sur n'importe quel case mémoire comme celle qui contien le mot de passe par exemple!!
     
    	cout<<"pointeur1: "<<pointeur1<<endl;//On trouve l'adresse sur laquelle pointeur1 pointe, il s'agit de: 0x7fff740c7750 
    	cout<<"*pointeur1 :"<<*pointeur1<<endl;// On trouve la valeure sur laquelle pointeur 1 pointe 
    	cout<<"&pointeur1"<<&pointeur1<<endl; //On trouvela case mémoire de la variable "pointeur 1"
    */
     
     
    //2)Déclaration d'un pointeur avec initialisation vers l' adresse d'une variable donnée 	
     
    	//On va "allouer" l' espace mémoire sufisant pour une variable de type "int". Puis on va "initialiser" sa valeure à 2. L'emplacement mémoire est munit d'une adresse. 'L'étiquette est le nom/l'identificateur ...)
    	string variable("lolo");
    	string *pointeur3(&variable);
    	cout<<endl<<"1) Déclaration d'un pointeur avec initialisation vers l' adresse d'une variable donnée "<<endl<<endl
    	<<"a) &variable (adresse de la variable:string variable(""lolo"");) :"<<&variable<<endl
    	<<"b) pointeur3 (adresse sur laquelle pointe pointeur3): "<<pointeur3<<endl
    	<<"c) *pointeur3 (valeure sur laquelle pointe pointeur 3: (ie) valeure de variable) :"<<*pointeur3<<endl
    	<<"d) &pointeur3(adressede la cae émoire de pointeur3) "<<&pointeur3<<endl;
     
     
     
     
    //2) Déclaration d'un pointeur avec initialisation vers l' adresse fictive 0  
     
     
    	int *pointeur4(0);//On crée un pointeur: donc on réserve une case mémoire (disons 53771) qui va contenir l' adresse d'une autre case mémoire réservée aux entiers. Pour le moment l'adresse dedans est 0 et correspond à rien
    	cout<<endl<<"2) Déclaration d'un pointeur avec initialisation vers l' adresse fictive 0 "<<endl<<"a) &pointeur4 (adresse du pointeur): "<<&pointeur4<<endl<<"b) pointeur4 (adresse sur laquelle pointe notre pointeur $int *pointeur4(0);$ ) : "<<pointeur4<<endl<<"c)*pointeur4 (valeure sur laquelle pointe pointeur 4, normalement segmentation fault car il pointe vers une adresse fictive) :"<<endl;//<<*pointeur4<<endl;
     
    //	3)Allouer un espace mémoire sur lequel notre pointeur pointera avec new
     
    	pointeur4=new int;// On demande manuellement une case mémoire pour stocker un entiers. Par exemple la case 14563 réservée à un entier. Du coup la case 53771 contient l'entier 14563 correspondant à l' adresse.
    	cout<<endl<<"3)Allouer un espace mémoire sur lequel notre pointeur pointera avec new"<<endl<<"a) pointeur4 (l'adresse sur laquelle pointe pointeur 4 après allocation pointeur4=new int; différent de 0 normalement): "<<pointeur4<<endl<<"b) *pointeur4 (la valeure sur laquelle pointe notre pointeur4): "<<*pointeur4<<endl<<"c) &pointeur4 : "<<&pointeur4<<endl;
    	*pointeur4=2;
    	cout<<"d) *pointeur4 (On modifie (*pointeur4=2;) la valeure de la variable sur laquelle pointe pointeur 4 on va passer de 0 à 2)): "<<*pointeur4<<endl;
     
    //	4) Supprimer avec delete (On libère la case mémoire: le pointeur ne peut plus y accéder, le pc peut donc l' utiliser comme bon lui semble)
     
     
    	cout<<endl <<"4) Supprimer avec delete (delete pointeur4;)"<<endl;
    	delete pointeur4;
    	cout<<endl<<"a) pointeur4 (l'adresse sur laquelle pointe pointeur 4 après allocation pointeur4=new int; différent de 0 normalement) "<<pointeur4<<endl<<"b) *pointeur4 (la valeure sur laquelle pointe notre pointeur4): "<<*pointeur4<<endl<<"c) &pointeur4 "<<&pointeur4<<endl;
    	*pointeur4=2;
    	cout<<"b) *pointeur4 (la valeure sur laquelle pointe notre pointeur4): "<<*pointeur4<<endl;
     
    	//cout<<"pointeur3: "<<pointeur3<<endl;// Le pointeur existe toujours mais plus le droit de l utiliser!
    	//cout<<"*pointeur3: "<<*pointeur3<<endl;
     
     
    	return 0;
    }
    Et j'obtient en console:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    a) &variable (adresse de la variable:string variable(lolo);) :0x7fffa866b000
    b) pointeur3 (adresse sur laquelle pointe pointeur3): 0x7fffa866b000
    c) *pointeur3 (valeure sur laquelle pointe pointeur 3: (ie) valeure de variable) :lolo
    d) &pointeur3(adressede la cae émoire de pointeur3) 0x7fffa866b010
     
    2) Déclaration d'un pointeur avec initialisation vers l' adresse fictive 0 
    a) &pointeur4 (adresse du pointeur): 0x7fffa866b018
    b) pointeur4 (adresse sur laquelle pointe notre pointeur $int *pointeur4(0);$ ) : 0
    c)*pointeur4 (valeure sur laquelle pointe pointeur 4, normalement segmentation fault car il pointe vers une adresse fictive) :
     
    3)Allouer un espace mémoire sur lequel notre pointeur pointera avec new
    a) pointeur4 (l'adresse sur laquelle pointe pointeur 4 après allocation pointeur4=new int; différent de 0 normalement): 0x211e040
    b) *pointeur4 (la valeure sur laquelle pointe notre pointeur4): 0
    c) &pointeur4 : 0x7fffa866b018
    d) *pointeur4 (On modifie (*pointeur4=2;) la valeure de la variable sur laquelle pointe pointeur 4 on va passer de 0 à 2)): 2
     
    4) Supprimer avec delete (delete pointeur4;)
     
    a) pointeur4 (l'adresse sur laquelle pointe pointeur 4 après allocation pointeur4=new int; différent de 0 normalement) 0x211e040
    b) *pointeur4 (la valeure sur laquelle pointe notre pointeur4): 0
    c) &pointeur4 0x7fffa866b018
    b) *pointeur4 (la valeure sur laquelle pointe notre pointeur4): 2
    laurent@Ellington:~/Dropbox/Code_C++/Pedagodie_prog$
    Je ne comprends pas! Le delete n'est il pas censer me detruire mon pointeur, ou du moins l' empecher d'acceder à la case mémoire sur laquelle il pointait auparavant ? J'ai du mal à bien comprendre!

  9. #49
    Membre émérite
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Points : 2 799
    Points
    2 799
    Par défaut
    Citation Envoyé par dfshr8 Voir le message
    Je ne comprends pas! Le delete n'est il pas censer me detruire mon pointeur, ou du moins l' empecher d'acceder à la case mémoire sur laquelle il pointait auparavant ? J'ai du mal à bien comprendre!
    delete dit simplement au programme : « détruit cet objet, et ensuite tu peux libérer cette mémoire, je n’en ai plus besoin ». Ça ne remet pas le pointeur à null (ceci est effectué par une affectation, réaffecter à null un pointeur après le delete est considéré par certains comme une bonne pratique).

    Le fait que cette mémoire soit effectivement bien libérée au niveau système, et inaccessible pour ton programme, en revanche, est laissé à la libre interprétation de celui qui a écrit ton compilateur (ou, plus précisément, l’allocateur mémoire). En général, ce n’est pas le cas. Ce que tu fais (accéder à un bloc de mémoire libéré) porte un nom : « comportement indéterminé » ou « undefined behaviour » en anglais (UB pour les intimes). Autrement dit, il peut se passer n’importe quoi, y compris le contraire de ce à quoi tu t’attendais.

    Dans plein de cas, ça va planter, mais ce n’est nullement une garantie. Si tu lances ton programme à l’aide d’un outil comme valgrind, par exemple, il te signalera cette erreur.

  10. #50
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2011
    Messages
    104
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2011
    Messages : 104
    Points : 23
    Points
    23
    Par défaut
    Citation Envoyé par white_tentacle Voir le message
    delete dit simplement au programme : « détruit cet objet, et ensuite tu peux libérer cette mémoire, je n’en ai plus besoin ». Ça ne remet pas le pointeur à null (ceci est effectué par une affectation, réaffecter à null un pointeur après le delete est considéré par certains comme une bonne pratique).

    Le fait que cette mémoire soit effectivement bien libérée au niveau système, et inaccessible pour ton programme, en revanche, est laissé à la libre interprétation de celui qui a écrit ton compilateur (ou, plus précisément, l’allocateur mémoire). En général, ce n’est pas le cas. Ce que tu fais (accéder à un bloc de mémoire libéré) porte un nom : « comportement indéterminé » ou « undefined behaviour » en anglais (UB pour les intimes). Autrement dit, il peut se passer n’importe quoi, y compris le contraire de ce à quoi tu t’attendais.

    Dans plein de cas, ça va planter, mais ce n’est nullement une garantie. Si tu lances ton programme à l’aide d’un outil comme valgrind, par exemple, il te signalera cette erreur.
    Merci, si j' ai un pointeur (notons le "p") sur la case: [ étiquetée "variable" d'adresse "3f0xx" et de valeure 3 (donc une zone de type entier)].
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    int x(3);
     
    int* p(&x)
    Puis que je fais:
    Que se passe t'il ?
    La case mémoire d'adresse "3f0xx" n'est plus réservée pour le programme (d'ailleurs après un delete la valeure a l'interieur de cette case mémoire est supprimée donc le cout nous donne la valeur 0 par défault), et donc un autre programme est suceptible de l'utiliser et y stocker par exemple la valeure 1 ? Du coup ce qu'il y a à l'interieure de cette case est aléatoire au cours du temps . Selon le moment où l'on executera notre programme on pourrait y voir toutes sortes de valeures (qui respecte le type entier) y circuler?
    Mais le pointeur p qui contient encore l' adresse "3f0xx" peut modifier la valeure de la case mémoire "3f0xx" sans garantie de la durée ou cette modification va perdurer. Est ce correcte ?

  11. #51
    Membre émérite
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Points : 2 799
    Points
    2 799
    Par défaut
    Non. Tu ne peux appeler delete que sur un pointeur qui pointe vers de la mémoire allouée avec new. Tout le reste relève du comportement indéterminé.

    Dans le cas présent, x étant sur la pile, il est vraisemblable que l’appel à delete fera planter ton programme. En revanche :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    int * x = new int(3);
    int* p = x;
    delete p;
    // à partir de maintenant, x ne pointe plus vers une adresse valide et le déréférencer risque de planter. Il ne faut pas non plus appeler delete dessus puisque la « case mémoire » a déjà été libérée
    Ce qu’il faut bien comprendre, c’est que toucher à de la mémoire non allouée, ou à de la mémoire libérée, est indéfini. Tu n’as pas le droit de le faire, et tu n’auras aucune garantie sur le comportement. Dans certains cas ça passera, dans d’autres ça plantera, mais cela relève le plus souvent du détail d’implémentation et de certaines conditions d’exécution que tu ne maîtrises pas (charge de l’os par exemple).

  12. #52
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 058
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 058
    Points : 12 093
    Points
    12 093
    Par défaut
    donc un autre programme est suceptible de l'utiliser et y stocker par exemple la valeure 1
    Ça fait plus de 20 ans que tous les OS non-embarqués (et beaucoup d'entre eux) sépare hermétiquement la mémoire entre les processus.
    Chaque processus dispose de son propre espace d'adressage.
    L'adresse "3f0xx" (adresse virtuelle, car c'est une adresse compréhensible que par le processus) d'un processus ne correspond pas à la même mémoire physique que cette même adresse dans un autre processus.
    Via les primitive de mapping mémoire, on peut faire en sorte que de la mémoire physiques soit accessibles par des processus différents, mais c'est de la programmation système assez bas niveau.
    Il n'y a donc, dans les faits, que le processus courant qui peut toucher à la valeur à l'adresse (virtuelle) "3f0xx", s'il y a de la mémoire physique associée, et c'est loin d'être automatique.
    Le malloc sert surtout à demander à la C-Runtime une plage d'adresse virtuelle associé à de la mémoire physique.
    Si la C-Runtime dispose d'une zone mémoire déjà associée à de la mémoire physique (via de la pré-allocation ou des deletes antérieurs) malloc retour l'adresse de cette page, sinon, la C-Runtime demande à l'OS de mapper plus de mémoire physique dans la mémoire virtuelle et malloc renvoie une adresse dans le nouveau bloc de mémoire nouvellement associé.
    Du coup ce qu'il y a à l'interieure de cette case est aléatoire au cours du temps
    Oui, mais c'est ton programme qui y met tout et n'importe quoi. Comme un delete ne fait que rendre la plage virtuelle d'adresse disponible pour les prochains malloc, ton programme fait ce qu'il veut avec.
    Si le système a besoin de mémoire physique, le C-runtime dissocié des pages entières de mémoires physiques de la mémoire virtuelle, pour que la mémoire physique puisse être utilisé par d'autres programmes.

    Selon le moment où l'on executera notre programme on pourrait y voir toutes sortes de valeures (qui respecte le type entier) y circuler?
    Le programme pourra y voir et y mettre tout et n'importe quoi, la mémoire n'est pas affecté par type, elle pourra contenir un int, un bout de float, plusieurs char, des pointeurs, ...
    Il pourra même se retrouver avec une zone de mémoire virtuelle plus associée à de la mémoire physique, et donc se prendre un bon gros segfault (peut, mais obligatoire quand cas de dissociation mémoire virtuelle / mémoire physique)
    Mais le pointeur p qui contient encore l' adresse "3f0xx" peut modifier la valeure de la case mémoire "3f0xx" sans garantie de la durée ou cette modification va perdurer. Est ce correcte ?
    Il n'est même pas sûr de pouvoir y lire, donc encore moins y écrire.

  13. #53
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2011
    Messages
    104
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2011
    Messages : 104
    Points : 23
    Points
    23
    Par défaut
    18)
    Selon ou je place le & je n'ai pas la ompilation:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    #include <iostream>
    #include<string>	
    using namespace std;
     
    struct 	Maison{
    	string adresse;
    };
    struct Personne{
    	string nom;
    	Maison& home;
    };
     
    void affiche(const& Personne p);
     
    void affiche(const& Personne p){
    	cout<<p.nom<<endl;
    	cout<<p.home.adresse<<endl; //On affiche ce qu'il ya dans la référence directement grâce à l' allias
    }
     
    int main()
    {
    	//Déclaration et initialisation découplée
    	Maison m1;//Allocation satique lors de la déclaration
    	m1.adresse = { "12 rue du chateau" };
     
    	//Ici à cause des références on doit faire simlatnment declaration et initialisation:
    	Personne p1 = { "Pierre", m1 };//Lorsque l'on initialise une référence on met le nom de la variable (et non son adresse!)
    	Personne p2 = { "Paul"  , m1 };
     
    	Maison m2 = { "13 rue du chateau" };
    	Personne p3 = { "Steve", m2 };
    	Personne p4 = { "Sofia", m2 };
     
    	affiche(p1);  affiche(p2);
    	affiche(p3);  affiche(p4);
     
     
    	return 0;
    }
    et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    #include <iostream>
    #include<string>	
    using namespace std;
     
    struct Maison {
      string adresse;
    };
     
    struct Personne {
      string nom;
      Maison& home;
    };
     
    void affiche(const Personne& p) {
      cout << p.nom << " habite " << p.home.adresse << endl;
    }
     
    int main()
    {
      Maison m1 = { "12 rue du chateau" };
      Personne p1 = { "Pierre", m1 };
      Personne p2 = { "Paul"  , m1 };
     
      Maison m2 = { "13 rue du chateau" };
      Personne p3 = { "Steve", m2 };
      Personne p4 = { "Sofia", m2 };
     
      affiche(p1);  affiche(p2);
      affiche(p3);  affiche(p4);
     
    	return 0;
    }
    Ce dernier fonctionne!
    marche!
    ne marche pas. La je crois comprendre: Personne contient un champ qui est une référene et qui doit donc obligatoirement être initialisé lors de sa déclaration.

    En fait j'ai un peu du mal à comprendre la différence entre les deux

  14. #54
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2011
    Messages
    104
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2011
    Messages : 104
    Points : 23
    Points
    23
    Par défaut
    19)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    cout<<p.home<<endl; //On affiche ce qu'il ya dans la référence directement grâce à l' allias
    ne marche pas.

    Alors que:
    Je ne comprends pas pourquoi on accede pas à la référenc directement par p.home?

  15. #55
    Membre émérite
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Points : 2 799
    Points
    2 799
    Par défaut
    Citation Envoyé par dfshr8 Voir le message
    18)

    marche!
    ne marche pas.
    Ici, c’est seulement une histoire de syntaxe et de convention. L’esperluette qui indique une référence doit se trouver avant la variable qu’elle déclare. Tu peux donc écrire :
    Ce qui déclare deux entiers, a et c, et une référence vers un entier (b est une référence vers a).

    Pour le const, il y a une subtilité. Normalement il s’applique à ce qui est à sa gauche, sauf s’il n’y a rien, auquel cas il s’applique à sa droite. Ainsi :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    int const& a = b;
    const int & c = b;
    sont équivalents.

    Citation Envoyé par dfshr8 Voir le message
    19)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    cout<<p.home<<endl; //On affiche ce qu'il ya dans la référence directement grâce à l' allias
    ne marche pas.

    Alors que:
    Je ne comprends pas pourquoi on accede pas à la référenc directement par p.home?
    C’est le principe du système de type. p.home est de type Adresse, et l’opérateur << n’est pas redéfini pour le couple flux, Adresse. Il y a une entrée de la FAQ pour ça . p.home.adresse est de type string, et là l’opérateur est défini, donc ça fonctionne.

  16. #56
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2011
    Messages
    104
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2011
    Messages : 104
    Points : 23
    Points
    23
    Par défaut
    Ah je crois que j'ai compris:

    p.home est une référence vers Maison, mais en tant que référence elle s'utilise comme la variable elle même (ie) une Maison. Or pour accéder à un champ d'une variable de type Maison on fait bien nomVariable.Champ. C'est bien ce que l'on fait ici!! p.home variable (référence en faite) de type Maison donc pour acceder au champ adresse: p.home.adresse

    Merci!

    Mais dans le cas des références est ce pareil ?

  17. #57
    Membre émérite
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Points : 2 799
    Points
    2 799
    Par défaut
    Une référence est réellement un alias vers une autre variable, et s’utilise de la même manière.

    Un point important par contre dans ton code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    struct 	Maison{
    	string adresse;
    };
    struct Personne{
    	string nom;
    	Maison& home;
    };
    Ici, la structure « Personne » ne contient pas une Maison, mais seulement une référence vers une Maison. C’est à dire qu’il ne contrôle pas la durée de vie de l’objet. En particulier, dans le cas suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    int main()
    {
        Maison* m = new Maison{"la maison"};
        Personne p { "Pierre", *m };
        delete m;
        std::cout << p.home.adresse; // KABOOOM (ou pas, en tout cas comportement indéterminé)
        return 0;
    }
    Parce que p.home fera référence à une variable détruite, et donc derrière de la mémoire libérée. En général, pour ce genre de structure qui sont plutôt des structure à sémantique de valeur, on n’utilise pas de référence mais bien des objets directement. On écrira plutôt :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    struct 	Maison{
    	string adresse;
    };
    struct Personne{
    	string nom;
    	Maison home;
    };

  18. #58
    Membre chevronné Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Points : 2 160
    Points
    2 160
    Par défaut
    Le code qui illustre le problème est très artificiel, le problème vient clairement du code utilisateur, on attend une référence et l'utilisateur donne un "pointeur casté en référence"...
    Les explications sont biens, en C++ on aime bien (voire on préfère) la sémantique de valeur

  19. #59
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2011
    Messages
    104
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2011
    Messages : 104
    Points : 23
    Points
    23
    Par défaut
    Voici l' énoncé de l' exercice:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    22.1 Références
     
    Créez une structure Maison contenant simplement une adresse (chaîne de caractères).
     
    Créez ensuite une structure Personne contenant un nom (chaîne de caractères) et une référence sur une Maison.
    Les différents habitants d'une maison n'ont en effet pas une copie de leur maison avec eux, mais simplement un moyen d'y référer (mémoire de l'adresse)...
    C'est un cas typique d'illustration des références.
     
    Créez ensuite deux maisons différentes dans le main(), puis créez des personnes différentes habitant dans des maisons différentes (plusieurs habitants par maison).
    La principale difficulté réside dans le fait qu'une référence doit toujours référencer quelque chose : il faut donc affecter les maisons dès l'initialisation.
     
    Pour finir cette partie : créez une fonction affiche qui affiche une personne en indiquant son nom et son adresse, par exemple :
     
    Pierre habite 12 rue du Château
     
    Affichez toutes les personnes de votre programme.
    22.2 Limites des références (niveau 2)
     
    Le cadre choisi ici illustre aussi les limites des références : avec cette implémentation
    , il est impossible à une personne de déménager : on ne peut en effet pas « changer de référence ».
     
    C'est parfait si c'est vraiment ce que l'on veut dans le programme (=on est sûr que personne ne déménagera), et il vaudrait alors mieux la déclarer comme référence constante.
    Mais si l'on voulait pouvoir faire déménager les personnes, il faudrait faire autrement... à vous de trouver comment.
     
    En clair : implémenter une seconde version du programme dans laquelle vous faites déménager au moins une personne.
    Assurez-vous que les autres personnes à la même (ancienne) adresse n'ont pas elles aussi déménagé (ce qui serait le cas avec des références :-( ).
    19)Ai je bien compris ? Voici mon interprétation:
    Lorsque j'utilise les références dans mon exemple je ne peux déménager. En effet une référence est attachée à une adresse ixée et ne peut donc désignr que la même case mémoire!! Donc dans mon code la Personne p1 a pour attribut/champs &Maison, la cae mémoire associée à la variable m1!. Si j voulais changer d'adresse il faudrait que je fasse p1.home=m2 (par exemple) mais ceci changerai l' adresse de m1 qui serait la me que m2 sans changer de Maison!

  20. #60
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2011
    Messages
    104
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2011
    Messages : 104
    Points : 23
    Points
    23
    Par défaut
    20)

    Pourquoi cei ne passe pas ? Il me semble pourtant que ce que je dis est logique ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    #include <iostream>
    #include<string>	
    using namespace std;
     
    struct 	Maison{
    	string adresse;
    };
    struct Personne{
    	string nom;
    	Maison* home;
    };
     
    void affiche(Personne const&  p);
     
    void affiche(Personne const&  p){
    	cout<<p.nom<<endl;
    	cout<<*(p.home).adresse<<endl; /*(p.home) désigne un pointeur vers une maison (car de type Maison*. Du coup pour accéder àl' adresse de la maison il faut utiliser le déférencement.Donc *p.home nous donne accés à la valeure (l'interieur de la ase mémoire) de la structure Maison. Puis pour accéder à l' adressedonc au champ de la variable n fait comme d'habitude: *(p.home).adresse
    	:On affiche ce qu'il ya dans la référence directement grâce à l' allias:
     
    	*/
    }
    Il semble que le compilateur réclame:

Discussions similaires

  1. [VBA-E] Questions en Vrac...
    Par Pouic dans le forum Macros et VBA Excel
    Réponses: 6
    Dernier message: 08/02/2006, 14h50
  2. [FLASH 8] Question sur la portée des objets.
    Par i_shinji dans le forum Flash
    Réponses: 1
    Dernier message: 02/11/2005, 18h18
  3. Question sur les librairies .lib
    Par elvivo dans le forum Autres éditeurs
    Réponses: 5
    Dernier message: 05/10/2005, 21h06
  4. Réponses: 3
    Dernier message: 13/08/2004, 19h52
  5. question de débutant sur les objets
    Par boucher_emilie dans le forum ASP
    Réponses: 3
    Dernier message: 06/08/2004, 11h51

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo