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

Langage C++ Discussion :

Trouble : Named rvalue


Sujet :

Langage C++

  1. #1
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 705
    Points
    2 705
    Par défaut Trouble : Named rvalue
    Hello,

    J'ai du mal à trouver un sens et un intérêt à une déclaration telle que :

    Quelqu'un pourrait-il m'éclairer ?

    Merci.

  2. #2
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2015
    Messages
    53
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

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

    Informations forums :
    Inscription : Octobre 2015
    Messages : 53
    Points : 85
    Points
    85
    Par défaut
    Bonjour,

    je pense qu'il s'agit d'une histoire de rvalue/lvalue

    par exemple :

    void func(int toto);

    peut etre appelé avec des lvalue et rvalue.
    c'est a dire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
      int n = 1;
      func(n); // ca marche
      func(1); //ca marche

    void func(int& toto);

    peut etre appelé avec des lvalue seulement.
    c'est a dire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
      int n = 1;
      func(n); // ca marche
      func(1); // marche pas
    void func(int&& toto);

    peut etre appelé avec des rvalue seulement.
    c'est a dire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
      int n = 1;
      func(n); // marche pas
      func(1); // ca marche

  3. #3
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 705
    Points
    2 705
    Par défaut
    J'ai bien compris les rvalue dans le cadre des arguments de fonction.

    Ce qui m'intrigue, ce sont les autres rvalues nommées, qui ne sont pas des arguments de fonction.

  4. #4
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2015
    Messages
    53
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

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

    Informations forums :
    Inscription : Octobre 2015
    Messages : 53
    Points : 85
    Points
    85
    Par défaut
    Citation Envoyé par oodini Voir le message
    J'ai bien compris les rvalue dans le cadre des arguments de fonction.

    Ce qui m'intrigue, ce sont les autres rvalues nommées, qui ne sont pas des arguments de fonction.
    Ah pardon j'avais mal compris ta question. C'est une bonne question effectivement, peut etre pour forcer une fonction func(int&& toto) a accepté func(a) ? C'est une idée comme une autre je n'ai pas testé ^^

  5. #5
    Membre expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    739
    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 : 739
    Points : 3 627
    Points
    3 627
    Par défaut
    Cela ne sert pas à grand chose et ne force pas le passage de paramètre en rvalue (c'est toujours passé par référence).

    Par contre, c'est utile avec des types proxys et du AAA.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    std::vector<int> v1;
    std::vector<bool> v2;
     
    for (int & x : v1){} // ok
    for (bool & x : v2){} // ne compile pas, *v.begin() est un type proxy (une classe std::vector<bool>::reference) non un bool &.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    for (auto && x : v1){} // ok, x est un int&
    for (auto && x : v2){} // ok, x est un type proxy

  6. #6
    Expert éminent
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 565
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 565
    Points : 7 648
    Points
    7 648
    Par défaut
    Bonjour,

    La r-reference est une référence qui s'initialise sur un temporaire (rvalue) ou une variable qui peut être dépecée (xvalue).
    Cela est utile en passage de paramètre en particulier pour des optimisations.

    L'intérêt dans une variable locale est de bloquer une référence sur un temporaire que l'on va modifier!
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Objet fct() {}
    Objet && x = fct(); // fct a retourné un objet, x permet de l'utiliser plus loin
    Objet &y = fct();    // erreur, on ne peut pas référencer un temporaire
    Objet const& z = fct(); // ok, la référence constante est toujours possible
    Objet u = fct();     // ok, mais une opération de recopie a dû être effectuée
     
    ++x.a;
    ++y.a; // erreur
    ++u.a;
    std::cout << x.a << z.a << u.a; //ok
    La r-référence permet donc d'accéder de manière optimale à un temporaire que l'on peut modifier. Ce cas est rare (proxies) ou souvent idiot, il faut préférer la l-référence constante.

  7. #7
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 705
    Points
    2 705
    Par défaut
    Bonjour,

    Mais pourquoi la dernière ligne du code suivant compile-t-elle, alors qu'on affecte à une lvalue une rvalue ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    int j = 3;
    int&& i = 5;
    i = j;
    Est-ce comme à l'intérieur de fonctions ?
    i est-il utilisable comme une l-value après son initialisation ?

  8. #8
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 705
    Points
    2 705
    Par défaut
    Bon, OK, je crois que j'ai compris : la nature rvalue est fugace. Une fois qu'on a passé l'expression de la déclaration/définition, on passe à une nature de lvalue.

    Cette rvalueness ne persiste pas dans le temps.

    Cette histoire de rvalue n'est donc vraiment été créée QUE pour permettre la surcharge de fonction.
    Alors que les lvalue peuvent être utilisées pour autre chose (création d'alias, notamment).

  9. #9
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 630
    Points : 10 556
    Points
    10 556
    Par défaut
    Non je pense que tu te trompes: What are rvalues, lvalues, xvalues, glvalues, and prvalues?

    En gros si je comprends bien [mais je ne maitrise pas les cas particuliers ], un rvalue c'est un temporaire.
    Le problème du temporaire, c'est qu'on ne peut pas le modifier (et en théorie ni le lire)

    Mais,
    • Si on retourne par valeur, c'est un prvalue: il y a recopie
    • Si on attrape en const reference (C++03), c'est un xvalue. Sa durée de vie a été étendue pour être seulement lu
    • Si on attrape en && (C++11), c'est une rvalue reference et on pourra modifier le temporaire: il y a transfert (move semantic) si je ne me trompe pas.


    Et le glvalue, j'ai l'impression que c'est pour exprimer un passage de paramètres non par valeur.

  10. #10
    Membre expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    739
    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 : 739
    Points : 3 627
    Points
    3 627
    Par défaut
    Les comportements de T et T&& sont identiques à travers une variable: on manipule un T&. Bah oui, toutes les variables sont des lvalues. D'où l'usage systématique de std::move en cascade quand on propage l'ownership et de std::forward dans les tempates.

    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
    #include <iostream>
     
    struct A{
      int foo() & { return 1; }
      int foo() && { return 2; }
    };
     
    int main() {
      A a{};
      A && ra{};
      std::cout
        << a.foo() << '\n' // 1
        << ra.foo() << '\n' // 1
        << A{}.foo() << '\n' // 2
        << static_cast<A&&>(a).foo() << '\n' // 2
        << static_cast<A&&>(ra).foo() << '\n' // 2
      ;
      //decltype(a){} = 1; // no match for ‘operator=’ (operand types are ‘A’ and ‘int’)
      //decltype(ra){} = 1; // no match for ‘operator=’ (operand types are ‘A’ and ‘int’)
    }

  11. #11
    Expert éminent
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 565
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 565
    Points : 7 648
    Points
    7 648
    Par défaut
    Citation Envoyé par jo_link_noir Voir le message
    Les comportements de T et T&& sont identiques à travers une variable: on manipule un T&. Bah oui, toutes les variables sont des lvalues. D'où l'usage systématique de std::move en cascade quand on propage l'ownership et de std::forward dans les tempates.
    Oui, c'est important d"avoir cela à l"esprit.
    Object x = ...;
    Object &y = ...;
    Object const&z = ...;
    Object &&u = ...;

    Ces quatre variables sont toutes des l-values (ces sont des variables, elles ont bien un nom).

    La différenciation n'a de sens qu'au moment de l'initialisation
    • x s'initialise sur tout (elle a son propre contenu)
    • y s'initialise obligatoirement sur une l-value
    • z s'initialise sur tout (si pr-value ou transformation nécessaire, le temporaire reçu qui normalement disparaît à la fin de l'expression est maintenu jusqu'à la fin de vie de z).
    • u s'initialise obligatoirement sur une r-value.

    A l'utilisation, on donc leur affecter tout ce que l'on veut (xvalue, prvalue, lvalue, glvalue, rvalue).
    les opérations sur y z u agissent sur le contenu référencé.

Discussions similaires

  1. [C++]Machine Name
    Par Dos dans le forum MFC
    Réponses: 4
    Dernier message: 14/01/2004, 17h19
  2. [EJB] [JBOSS][javax.naming.NameNotFoundException]
    Par hamed dans le forum Java EE
    Réponses: 5
    Dernier message: 18/12/2003, 18h00
  3. [XSL] insérer une balise <a name>
    Par guibong dans le forum XMLRAD
    Réponses: 2
    Dernier message: 01/08/2003, 15h04
  4. TXMLModule.create - name = resource not found
    Par pram dans le forum XMLRAD
    Réponses: 2
    Dernier message: 04/03/2003, 10h54
  5. naming service
    Par manuel dans le forum CORBA
    Réponses: 6
    Dernier message: 09/12/2002, 17h43

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