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 :

Rvalue et move (encore et toujours)


Sujet :

C++

  1. #1
    Débutant
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    688
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2006
    Messages : 688
    Points : 176
    Points
    176
    Par défaut Rvalue et move (encore et toujours)
    Ecnore une question autour des concept des Rvalue references et du move semantics :

    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
     
    struct Foo
    {
    	int n;
    	explicit Foo(int m):n(m)
    	{
    		std::cout << "constructeur\n";
    	} 
    	Foo(const Foo& n)
    	{ 
    		std::cout << "constructeur copie\n";
    	}
    	Foo(Foo&& n)
    	{ 
    		std::cout << "constructeur move\n";
    	}
    };
     
    Foo make()
    {
    	return Foo(3);
    }
     
    int main()
    { 	  	 
    	Foo po( make() );  //ok mais affiche uniquement constructeur ?!
    	std::cout << " " << po.n;
    	system("pause");
     
    }
     
    int main()
    { 	  	 
    	Foo po( move(make()) );  //passe bien dans le move ctor
    	std::cout << " " << po.n; // affiche n'importe quoi?!
    	system("pause");
     
    }
    Deux questions :

    pourquoi dans le premier main , on ne passe ni dans le ctor de copie ni dans le ctor de move ?

    pourquoi dans le 2eme cas, ça affiche n'importe quoi ?

    Merci.

  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
    1/ NRVO + Copy-Elision : Le compilateur choisit de ne pas faire les copies intuiles, c'est à dire celles à la sortie de la fonction, et celle avec le copy_ctor, il créé directement l'objet sur place.

    2/ Le NRVO agit une première fois à la sortie de la fonction (sinon tu aurais ctor copy_ctor, et pas seulement ctor), puis tu utilises std::move donc il n'y a plus de copy-elision possible, et le move_ctor est utilisé.

    Pour la valeur c'est normal, ca a beau être une move_ctor, ca reste un contructeur, si tu ne donnes pas de valeur à ton attribut il est non-initialisé, et donc ca valeur c'est n'importe quoi.

    Pour ce qui concerne la sémantique de mouvement et les rref, il y a une séries d'articles sur le sujet sur cppnext, avec un rappel sur le (N)RVO et la copy-ellision au début. (Et il y a plusieurs exemples qui permettent de bien comprendre)

  3. #3
    Débutant
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    688
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2006
    Messages : 688
    Points : 176
    Points
    176
    Par défaut
    très clair merci.
    j'étais passé à côté de la copy-Elision

    du coup ça me laisse perplexe quand à l'utilité réel de la move semantics, ok pour le move quand on veut forcer une lvalue en rvalue mais à part ça ...??

  4. #4
    Membre chevronné
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Points : 1 921
    Points
    1 921
    Par défaut
    Citation Envoyé par guillaume07 Voir le message
    très clair merci.
    j'étais passé à côté de la copy-Elision

    du coup ça me laisse perplexe quand à l'utilité réel de la move semantics, ok pour le move quand on veut forcer une lvalue en rvalue mais à part ça ...??
    La move semantic reste utile pour la construction par vol de ressource. Un temporaire est passé a un op= ou un ctor, tu echange les ressources et hop.

  5. #5
    Débutant
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    688
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2006
    Messages : 688
    Points : 176
    Points
    176
    Par défaut
    on est bien d'accord que dans un code comme celui là :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    std::vector<std::string> v;
    {
    std::string s = "sometext";
    v.push_back( std::move(s) );
    //s ne doit pas être accédé ??
    }
    //v[0] est toujours valide ??

  6. #6
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par guillaume07 Voir le message
    on est bien d'accord que dans un code comme celui là :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    std::vector<std::string> v;
    {
    std::string s = "sometext";
    v.push_back( std::move(s) );
    //s ne doit pas être accédé ??
    }
    //v[0] est toujours valide ??
    J'ai pas suivi ça de trop trop près (Loic?), mais ce qu'on garanti pour les types standards après qu'ils aient ete deplaces, ce qu'on exige des types arguments template de la SL et ce qui est fournit d'office et dans quelles circonstances pour les types declares par l'utilisateur était un des gros sujets de discussion lors du dernier meeting du comité.

    Autrement dit, même s'il n'est pas impossible que tu puisses faire quelque chose avec s, ne fait rien pour le moment, c'est pas impossible que ca ait change, c'est pas impossible que ca change.
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  7. #7
    Membre chevronné
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Points : 2 205
    Points
    2 205
    Par défaut
    Non, s ne doit pas être accédé, tu lui a volé ses ressources. Quand tu vois un move, tu touches plus à la ressource qui a été bougé. (et oui v[0] est toujours valide).

    (note que ma version de la STL ne fournit pas de constructeur prenant une rvalue ref ni d'op=)
    "Hardcoded types are to generic code what magic constants are to regular code." --A. Alexandrescu

  8. #8
    Membre émérite

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Points : 2 252
    Points
    2 252
    Par défaut
    Citation Envoyé par Goten Voir le message
    Non, s ne doit pas être accédé, tu lui a volé ses ressources.
    Jean-Marc.Bourguet a raison, on ne peut pas être aussi affirmatif Goten, car l'état d'un objet que l'on vient de déplacer a toujours été sujet à débat au comité et encore maintenant n'est pas fixé. (Je fais pas parti du comité hein , c'est ce j'en déduis à la lecture des papiers) Il y a d'ailleurs dans le dernier mailing un papier de Stroustrup qui tente de faire un résumé et propose une solution de plus.
    Citation Envoyé par Bjarne Stroustrup, N3201, Moving right along
    I think that the original idea was that a moved-from object would never be used again. The canonical example was “return x;” where move would save us from an expensive copy of x followed by the destruction of x. It follows that the moved-from state must be destructible. It was soon decided that in addition, it would help programmers (especially library builders) if it was possible to assign to a moved-from object. However, even that was not obvious to all and attempts to require further guarantees for the moved-from state elicited strong opposition. The consensus seems to be that a moved-from state must be “valid but unspecified” exactly as an object after a throw under the basic guarantee, but that nothing more can be guaranteed (except possibly for some specific type).

    The obvious state of a moved-from object is the “empty state.” The snag is that for some types there is no obvious “empty state” (e.g., consider proxies). How would we know if there was an empty state for a type X? Consider default construction. If there is a default constructor, we have an empty state – and by implication – we have an excellent candidate for the moved-from state. Assuming that we equate “establishing the invariant” with “constructing”, the existence of a default constructor ensures that there is a way to establish the invariant without running multiple operations or supplying arguments. Ignoring details, the obvious default move becomes:
    1. Move each element
    2. Default construct the moved-from object
    This observation leads to the idea: Generate a move operation for X only if we can default construct an X. There may be other constraints on generation; in particular, the ones I suggested in N3174. Let’s explore.

  9. #9
    Membre chevronné
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Points : 2 205
    Points
    2 205
    Par défaut
    Citation Envoyé par Arzar Voir le message
    Jean-Marc.Bourguet a raison, on ne peut pas être aussi affirmatif Goten, car l'état d'un objet que l'on vient de déplacer a toujours été sujet à débat au comité et encore maintenant n'est pas fixé.
    "Rule of thumb" pour éviter les ennuis.. C'est pas incompatible avec ce que dis Jean-Marc, c'est juste que pour éviter les ennuis je préfère le dire clairement comme ça. (par exemple, dans ma version de la SL, un std::vector à l'heure actuelle ses pointeurs pointent vers NULL après qu'il ai été déplacé).
    J'avais mal lu ce que disais Jean-Marc mais il en était arriver à la même conclusion que moi, dans le doute, ne pas s'en servir.
    "Hardcoded types are to generic code what magic constants are to regular code." --A. Alexandrescu

  10. #10
    Membre émérite

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Points : 2 252
    Points
    2 252
    Par défaut
    Ok, désolé, j'avais mal compris. En effet, dans le doute vaut mieux s'abstenir pour le moment.

Discussions similaires

  1. Clic droit encore et toujours
    Par Stéphane Olivier BERNARD dans le forum Access
    Réponses: 3
    Dernier message: 22/05/2006, 00h26
  2. IE/Firefox... encore et toujours...
    Par maniaco_jazz dans le forum Balisage (X)HTML et validation W3C
    Réponses: 7
    Dernier message: 19/02/2006, 23h17
  3. nodes, child et compatibilité... encore et toujours
    Par pmithrandir dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 28/04/2005, 14h26
  4. stencil buffer, encore et toujours
    Par JAimeBienCoderBourre dans le forum OpenGL
    Réponses: 4
    Dernier message: 08/04/2005, 11h16

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