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 :

[C++11] Déplacer un objet incopiable


Sujet :

C++

  1. #1
    Membre émérite
    Avatar de Daïmanu
    Homme Profil pro
    Développeur touche à tout
    Inscrit en
    Janvier 2011
    Messages
    696
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur touche à tout

    Informations forums :
    Inscription : Janvier 2011
    Messages : 696
    Points : 2 438
    Points
    2 438
    Par défaut [C++11] Déplacer un objet incopiable
    Bonjour.

    Je cherche à faire un jeu de carte et j'en suis à la définition des classes de base.

    J'ai un problème lorsque le jeu cherche à créer une Main en piochant dans le deck :

    Voici une version simplifiée de mon problème :
    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
    #include <deque>
    #include <iostream>
     
    class Card {
        enum Rank {/*As à Roi*/} m_rank;
        enum Suit {/*Couleurs*/} m_suit;
     
        Card(Rank rank, Suit suit) :
    	m_rank(rank), m_suit(suit) {}
     
        Card(Card &&other) :
            m_rank(std::move(other.m_rank)), suit(std::move(other.m_suit)) {}
     
        Card& operator= (Card &&other) {
            m_rank = std::move(other.m_rank);
            m_suit = std::move(other.m_suit);
            return *this;
        }
     
        Card(const Card&) = delete;
        Card& operator= (const Card&) = delete;
    };
     
    class Deck {
        /**
         * Creates 52 cards.
         */
        Deck();
        /**
         * @brief draw
         * Extract the front card.
         * After this function, the deck won't be full anymore.
         * @return the front card of the deck
         */
        Card &&draw() {
            auto card(std::move(m_cards.front()));
            m_cards.pop_front();
            return std::move(card);
        };
     
        std::deque< Card > m_cards;
    };
     
    int main(int, char**) {
        Deck d;
        auto c = d.draw();
        std::cout << c.m_rank << '\n';
        return 0;
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    g++ main.cpp -Wall -Wextra -std=c++11 && ./a.out 
    -110905296
    Le code compile mais le problème vient de la fonction Deck::draw() qui renvoie une carte avec des valeurs aléatoires.
    Je pense que le problème vient de la sémantique de mouvement que je ne maîtrise pas encore assez.

    D'après vous d'où vient le problème ?
    Je fais appel aux esprits de Ritchie, Kernighan, Stroustrup et Alexandrescu
    Donnez moi la force, donnez moi le courage de coder proprement !

    « Ça marche pas » n'est PAS une réponse convenable, merci de détailler le souci en fournissant l’environnement, le code source, les commandes et les messages d'erreur.

    Ce club possède également un clavardage, on y trouve quelques perles entre deux sessions d'entraides.

  2. #2
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    Bonjour,

    Tes opérations par déplacement ne font rien de spécial, tu peux donc laisser le compilateur les écrire avec =default, de plus quand tu déclare une opérations par copie ou par déplacement, la génération automatique des autres est désactivé, il est inutile de désactiver explicitement les opérations par copies :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    struct Card
    {
    	enum Rank { /*stuff*/ } m_rank;
    	enum Suit { /*stuff*/ } m_suit;
     
    	Card(Rank rank, Suit suit) :
    		m_rank(rank), m_suit(suit)
    	{ }
     
    	Card(Card&&) =default;
    	Card& operator=(Card&&) =default;
    };
    Ensuite, on ne retourne jamais une référence sur un objet local, que ce soit une lref ou un rref. Ce que ta fonction draw doit retourner c'est bien un objet, pas une référence, donc tu indiques directement le type Card, c'est lors du return que cet objet doit être construit en déplaçant une ressource. Dans ton cas le return est fait sur un objet local à la fonction, ce qui implique qu'elle est automatiquement déplacé, tu n'as même pas besoin d'indiquer le move :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    struct Deck
    {
    	Card draw()
    	{
    		auto card(std::move(m_cards.front()));
    		m_cards.pop_front();
    		return card;
    	}
     
    	std::deque<Card> m_cards;
    };

  3. #3
    Membre émérite
    Avatar de Daïmanu
    Homme Profil pro
    Développeur touche à tout
    Inscrit en
    Janvier 2011
    Messages
    696
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur touche à tout

    Informations forums :
    Inscription : Janvier 2011
    Messages : 696
    Points : 2 438
    Points
    2 438
    Par défaut
    C'est aussi simple que ça ?

    Merci, ça marche maintenant .
    Je fais appel aux esprits de Ritchie, Kernighan, Stroustrup et Alexandrescu
    Donnez moi la force, donnez moi le courage de coder proprement !

    « Ça marche pas » n'est PAS une réponse convenable, merci de détailler le souci en fournissant l’environnement, le code source, les commandes et les messages d'erreur.

    Ce club possède également un clavardage, on y trouve quelques perles entre deux sessions d'entraides.

  4. #4
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    Ça répond à ta question, après on a pas parlé de la prise en compte des exceptions dans ton code.

    Cependant tu as de la chance, toutes tes fonctions peuvent être qualifiées en noexcept. On peut aussi rajouter une assertion pour vérifier que le deck n'est pas vide lors de l'appel à draw.

    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
     
    #include<cassert>
    #include<deque>
     
    struct Card
    {
    	enum Rank {
    		As
    	} m_rank;
    	enum Suit {
    		Coeur
    	} m_suit;
     
    	Card(Rank rank, Suit suit) noexcept
    		: m_rank(rank)
    		, m_suit(suit)
    	{ }
     
    	Card(Card&&) noexcept
    		=default;
    	Card& operator=(Card&&) noexcept
    		=default;
    };
     
    struct Deck
    {
    	Card draw() noexcept
    	{
    		assert(!m_cards.empty() && "Deck empty");
     
    		auto card(std::move(m_cards.front()));
    		m_cards.pop_front();
    		return card;
    	}
     
    private:
    	std::deque<Card> m_cards;
    };
    On pourrait rajouter des constexpr à plusieurs endroit, mais je ne suis pas convaincu de l'intérêt ici.

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

Discussions similaires

  1. Déplacer un objet dans Dreamweaver
    Par mereyj dans le forum Dreamweaver
    Réponses: 4
    Dernier message: 18/01/2009, 16h28
  2. Déplacer des objets 3D
    Par pavicf dans le forum DirectX
    Réponses: 2
    Dernier message: 09/11/2006, 10h41
  3. déplacer un objet TLabel sur une Form
    Par darkangel37 dans le forum C++Builder
    Réponses: 14
    Dernier message: 14/06/2006, 10h36
  4. Déplacer des objets dans un JPanel
    Par hammag dans le forum AWT/Swing
    Réponses: 6
    Dernier message: 23/03/2006, 11h13
  5. [POO] Déplacer un objet avec un pas.
    Par Olaf MENJI dans le forum Général JavaScript
    Réponses: 1
    Dernier message: 28/12/2005, 13h32

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