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 :

Allocation dynamique en memoire


Sujet :

C++

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    146
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 146
    Par défaut Allocation dynamique en memoire
    Bonjour,

    Je voudrais savoir ce que signifie de faire:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Couleur* grille= new Couleur[taille*taille]
    Il me semble que Couleur* grille veut dire qu'on alloue un pointeur grille sur une Couleur et que new Couleur[taille*taille] alloue de l'espace en mémoire et renvoi l'adresse pointé par grille?

    ce qui me perturbe c'est surtout le fait de faire [taille*taille] que je ne pige pas très bien cette expression si c'est une matrice pourquoi on ne ferais pas [taille][taille]

  2. #2
    Membre éprouvé Avatar de Xtrem_Voyageur
    Homme Profil pro
    Inscrit en
    Juin 2009
    Messages
    85
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2009
    Messages : 85
    Par défaut
    Si tu as une matrice d'entiers de taille N*M donc N lignes et M colonnes, tu peux en effet la déclarer de 2 façons.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    int matrice[N][M]; // Dans ce cas on accède aux éléments en faisant matrice[i][j] avec 0<= i <= N et 0<= j <= M mais également en faisant matrice[i*M+j]
    int matrice[N*M]; // Ici, tu accèdes à l'élément matrice[i][j] en faisant matrice[i*M+j]
    Quoi qu'il en soit en mémoire, que tu déclares un tableau double ou simple, tes éléments seront contigus en mémoire, donc en gros en mémoire, c'est un tableau simple de taille N*M. Et voilà pourquoi en déclarant un double tableau, tu peux toujours accéder aux éléments à l'aide d'un simple indice.

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    146
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 146
    Par défaut
    euh j'ai pas tous pigé sur ton argumentation concernant l'accès au éléments...et comment on peux parcourir tous les éléments?

  4. #4
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    760
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2011
    Messages : 760
    Par défaut
    Se que dit Xtrem_Voyageur est valable pour un tableau sur la pile. Un tableau sur le tas (alloué avec new) ne peut pas être initialisé avec new int[n][m] car cette syntaxe voudrait dire "un pointeur pouvant contenir N pointeur de M int (un int **)". Hors, un int** n'est pas un tableau aligné car chaque colonne est allouer indépendamment des lignes (new alloue un bloc de donnée, pas une multitude de bloc). Pour avoir un segment aligné, il faut un bloc de N*M int.


    tableau une dimension de taille (5*2):

    int int int int int int int int int int

    (10 int alignés)


    tableau deux dimensions de taille (5*2)

    int * -> int int
    int * -> int int
    int * -> int int
    int * -> int int

    (5 int* alignés + 10 int alignés par groupe de 2)


    (Mon explication est quelque peu brouillon :/)

  5. #5
    Membre éprouvé Avatar de Xtrem_Voyageur
    Homme Profil pro
    Inscrit en
    Juin 2009
    Messages
    85
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2009
    Messages : 85
    Par défaut
    Oui, j'ai été un peu rapide.
    Si tu tiens absolument à utiliser la notation standard tant utile en algèbre linéaire, tu peux mais il faut modifier ta déclaration.
    En effet au lieu d'allouer un segment mémoire. Il va falloir que tu utilises un double pointeur pour pointer sur un tableau de pointeurs de Couleur.
    Chacun de ces pointeurs dans ce tableau devra lui même s'allouer un tableau de Couleurs. Ce n'est pas très compliqué mais cela demande plus
    de lignes de code.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    Couleur **grille = new Couleur*[N];
    for(int i = 0; i <N; ++i) {
      grille[i] = new Couleur[M];
    }
    // Et là tu peux utiliser ta grille avec la notation grille[i][j] en contrôlant tes i,j pour qu'ils restent dans les bornes, cela va sans dire.
    Ce qui implique de libérer correctement la mémoire.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    for(int i = 0; i < N; ++i) {
      delete [] grille[i]; // Ici on libère la mémoire occupée par les N tableaux de M Couleurs.
    }
    delete [] grille; // Ici on libère la mémoire occupée par la tableau de N pointeurs sur des Couleurs.
    Donc tu vois avec qu'avec la première notation, tu n'as qu'une allocation à faire, et une seule libération de mémoire.

    Sinon tu peux aussi utiliser des conteneurs de la STL comme std::vector, cela serait plus simple et serait plus dans l'optique de coder en C++
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    using std::vector;
    vector<vector<Couleur> > grille;
    grille.resize(N);
    for(int i = 0; i < N; ++i) {
      grille[i].resize(M);
    }
    // Tu as accès à un élément via la notation grille[i][j] comme tu voulais
    Et là, tu n'as plus à te soucier de la mémoire. L'objet vector a un allocateur de mémoire par défaut qui se charge de ça pour toi.
    (Attention tout de même si tu veux un vecteur de pointeurs, mais on ne va pas pousser plus loin pour le moment).

  6. #6
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    146
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 146
    Par défaut
    Ok mais dans ce cas la il m'est difficile d'interpréter un bout de code, que g tiré d'un livre, à partir de ce que vous venez de m'expliquer.

    la classe Jeu:
    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
     
    #ifndef JEU_HPP
    #define JEU_HPP
     
    #include "Joueur.hpp"
    #include <iostream>
    using namespace std;
     
    class Jeu {
    public:
    	Jeu(unsigned int t = 8);
    	Jeu(const Jeu&);
    	virtual ~Jeu();
     
    	Jeu& operator=(const Jeu&);
    	bool jouer(unsigned int numero, Couleur couleur);
    	unsigned int get_taille() const { return taille; }
    	ostream& affiche(ostream& sortie) const;
    protected:
    	unsigned int taille;
    	Couleur* grille;
    };
     
    #endif
    Jeu.cpp:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
     
    bool Jeu::jouer(unsigned int numero, Couleur couleur) {
    	if(couleur==vide) return false;
    	if(numero>=taille) return false;
    	const unsigned int k(taille*numero);
    	unsigned int j(0);
    	while((j<taille) && (grille[k+j] != vide))
    		++j;
    	if(j>=taille) return false;
    	grille[k+j] = couleur;
    	return true;
    }
    Je n'ai pas tous mis, juste l'aspect parcours des elements dans la matrice carrée. C'est tiré d'un exercice de puissance 4 et l'objectif est de placer un jeton de couleur dans une colonne dont le numero est passé en paramètre. J'ai essayé de le decortiquer mais ca correspond pas avec vos explications

    Desolé d'être aussi insistant mais j'ai besoin de comprendre ce mecanisme ca me parait important de le comprendre.

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    146
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 146
    Par défaut
    ah oui et la memoire est alloué de facon dynamique dans le livre de cette facon:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
     
    Jeu::Jeu(unsigned int t) {
    	taille = t;
    	grille = new Couleur[taille*taille];
    }

  8. #8
    Membre éprouvé Avatar de Xtrem_Voyageur
    Homme Profil pro
    Inscrit en
    Juin 2009
    Messages
    85
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2009
    Messages : 85
    Par défaut
    Tout dépend de la représentation que tu choisis.
    Dans la vrai vie, ton jeu de puissance 4 peut se représenter ainsi.
    A B C D
    E F G H
    I J K L
    M N O P

    Notons les colonnes de 0 à 3 et les lignes de 0 à 3.
    Si tu insères un jeton en colonne 2, tu pourras l'insérer en O si O est libre, sinon en K si K est libre, ... en remontant ta colonne.

    Si dans ton programme tu as choisi de représenter ton puissance 4 avec une matrice identique à mon dessin c'est à dire où
    grille[0][0] = A, ..., grille[0][3] = D
    ....
    grille[3][0] = M, ..., grille[3][3] = P
    alors il faut vérifier pour insérer un jeton en colonne 2 que grille[i][2] est libre pour i=0, puis pour i=1 si c'est occupé pour i = 0, etc..
    mais grille[i][2] correspond à grille[i*taille+2] dans ton code vu que tu as un tableau simple.
    En mémoire, les éléments ont été placé comme cela : A B C D E F G H I J K L M N O P

    L'auteur lui a décidé pour des raisons pratiques de représenter sa matrice comme cela
    M I E A
    N J F B
    O K G C
    P L H D
    et vu qu'il utilise un tableau simple, ses éléments sont en mémoire disposés dans l'ordre suivant : M I E A N J F B O K G C P L H D
    Donc tu vois bien que pour insérer un jeton en colonne 2 il toujours vérifier que O est libre puis K est libre, mais cette fois cela correspond à
    grille[2][j] pour j allant de 0 à 3 ou encore dans ton code à grille[2*taille + j] pour j allant de 0 à 3.

    Mais ne mélanges pas les 2 problèmes que tu as.
    Le premier qui est comment allouer et libérer de la mémoire en C ++ pour des tableaux simples ou doubles.
    Le deuxième étant plus conceptuel vis à vis de l'exercice et comment représenter un jeu de puissance 4 en mémoire.

  9. #9
    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 : 51
    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
    Par défaut
    Dans ton exemple, il traite d'un tableau 2D comme d'un tableau 1D :

    Peut être vu comme :
    Pour un tableau à 2 dimensions de M lignes et N colonnes, on alloue alors un tableau à 1 dimension de M*N cases.
    Et là où tu voulais accéder à la case (i,j), il te faudra accéder à la case (i*taille d'une ligne + j).

    Dans ton exemple, l'allocation new Couleur[taille*taille]; indique donc un tableau carré, ayant taille comme nombre de lignes et colonnes. Pour accéder à une case, on a bien :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    const unsigned int k(taille*numero);
    //....
    grille[k+j] = couleur;
    Ce qui correspond à mon (i*taille d'une ligne + j), sauf qu'il a inversé lignes et colonnes, ce qui est parfaitement autorisé, ce n'est qu'une convention (c'est à dire que dans mon tableau mis à plat, il aurait vu AEIBFJCGKDHL), et qui doit représenter le fait que pour un puissance 4, il souhaite donner plus d'importance à la colonne qu'à la ligne, en particulier pour savoir où s'arrête un pion que l'on met en jeu.
    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.

  10. #10
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    146
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 146
    Par défaut
    Ah ok c bon j'ai parfaitement bien compris avec vos explications...et merci d'avoir pris le temps de tous détailler

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 4
    Dernier message: 17/06/2014, 17h45
  2. [C] Allocation dynamique de memoire
    Par xc78370 dans le forum C
    Réponses: 9
    Dernier message: 29/11/2006, 18h57
  3. Allocation Dynamique de Memoire Avec Operateur New
    Par msstaf dans le forum C++Builder
    Réponses: 3
    Dernier message: 30/06/2006, 15h49
  4. Allocation dynamique de memoire
    Par beb30 dans le forum C
    Réponses: 5
    Dernier message: 25/04/2006, 18h06

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