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 :

shared_ptr en paramètre par référence ou par copie ? 


Sujet :

C++

  1. #1
    Membre éclairé Avatar de Suryavarman
    Homme Profil pro
    Développeur 3D
    Inscrit en
    Mai 2006
    Messages
    233
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Développeur 3D
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Mai 2006
    Messages : 233
    Par défaut shared_ptr en paramètre par référence ou par copie ? 
    J’ai cette question qui me revient souvent.

    A chaque fois que je passe un pointeur partagé en paramètre je me demande si je dois le faire passé par référence.

    Exemple:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    void Toto(std::shared_ptr<Lala>& lala)
    {}
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    void Toto(std::shared_ptr<Lala> lala)
    {}
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    void Toto(const std::shared_ptr<Lala>& lala_const)
    {}
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    void Toto(const std::shared_ptr<Lala> lala_const)
    {}
    etc


    Quel raisonnement suivez-vous/conseillez-vous pour faire votre choix?

  2. #2
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 391
    Par défaut
    Dans tous les cas l'objet lui-même ne sera pas copié.
    Je dirais passe le shared_ptr par copie tant que tu n'as pas passé ton code au profileur et déterminé que cet appel de fonction était performance-critical.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  3. #3
    Membre Expert
    Avatar de skeud
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2011
    Messages
    1 091
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Juin 2011
    Messages : 1 091
    Billets dans le blog
    1
    Par défaut
    De mon point de vu:
    Il faut le passer en copie et non en référence. Le but des shared_ptr, est de pointer le nombre de référence dans chaque contexte, comme tu appelles une nouvelle fonction, tu augmente le nombre de contexte, donc on incrémente .
    Imaginons que tu décides de threader ton appel de fonction, si tu le passes en référence, tu pourrais avoir des surprises ^^
    D'autant plus qu'une copie d'un shared_ptr est très peu couteuse en cpu, donc pas trop de raison de vouloir changer ça

    Ne jamais oublier "KISS"

  4. #4
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 145
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 145
    Billets dans le blog
    4
    Par défaut
    De base, le passage par référence tu oublies direct. Ce truc est là uniquement pour modifier le paramètre dans la fonction pour l'appelant.

    Maintenant que l'on sait que la bataille se situe entre const& et copie, on y réfléchit 2 minutes.
    Est-ce que la fonction ne fait qu'utiliser le paramètre sans le toucher ? Parfait, il peut être const&, son passage sera optimisé et l'appelant n'aura aucune surprise.
    Est-ce que la fonction modifie le paramètre en interne ? Alors tu demandes une copie. La copie aura pour effet que l'appelant pourra move sa variable si possible et donc aucune copie ne sera faite.

    Le cas de shared_ptr est un peu plus subtil parce que c'est le shared_ptr qui serait copié ou const mais pas son objet interne. Mais cette copie coûte avec le compteur de référence, ce qui peut être non négligeable.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  5. #5
    Membre Expert
    Avatar de skeud
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2011
    Messages
    1 091
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Juin 2011
    Messages : 1 091
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Bousk Voir le message
    Le cas de shared_ptr est un peu plus subtil parce que c'est le shared_ptr qui serait copié ou const mais pas son objet interne. Mais cette copie coûte avec le compteur de référence, ce qui peut être non négligeable.
    La création d'un shared_ptr par copie et donc incrémentation du compteur de référence est vraiment dimensionnant en terme de cout cpu? (Je connais pas trop, j'ai pas regarder les bench la dessus donc je pose la question ^^)

  6. #6
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 145
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 145
    Billets dans le blog
    4
    Par défaut
    Sur TotoProject sûrement pas, sur un vrai projet où tu as potentiellement des centaines/milliers de ces trucs et du code exécuté sur plusieurs threads et cores...
    Ça a beau s'améliorer, utiliser des atomic, intrinsics etc, ça reste un moment un truc alloué et synchronisé.
    La différence entre 30fps et 60fps c'est ~16ms/frame, c'est (très) peu et tout compte.

    Le mieux étant de ne pas utiliser de shared_ptr.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  7. #7
    Membre Expert Avatar de Astraya
    Homme Profil pro
    Consommateur de café
    Inscrit en
    Mai 2007
    Messages
    1 048
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Consommateur de café
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2007
    Messages : 1 048
    Par défaut
    Hello,

    Ne cherche pas trop à faire trop d'optimisation si tu n'en as pas le besoin.
    Il faut comprendre que std::atomic n'est pas gratuit. Le problème avec la version standard c'est quelle considère qu'elle doit être thread-safe et utilise en interne un std::atomic pour gérer ses compteurs.
    Les std::atomics sont bien plus lent qu'une simple incrémentation d'un entier. ( Petit benchmark ici ).
    Donc ici on pointe un problème avec std::atomic, on ne peux pas choisir si on veut payer le coût du multi-thread ou pas. ( C'est pour ça que dans les applications qui demande beaucoup de performance, par exemple les jeux vidéos, on recréer les std::shared_ptr pour choisir la synchro thread-safe ou pas. Voir Unreal Engine TSharedPtr<FMyObjectType, ESPMode::ThreadSafe> )
    Ensuite, forcement faire une copie sera plus lent, TRES lent par rapport à une référence. ( Autre petit benchmark ici ).

    Tu peux faire ta référence, il n'y a aucun problème la dessus. Il faut bien comprendre que faire une copie d'un std::shared_ptr c'est comme partager le ownership, or si ta fonction veux juste l'utiliser mais pas avoir le ownership, tu peux et doit faire une référence.
    Ce concept s'applique dans le langage Rust sous le nom "Borrowing and Ownership", il faut faire la distinction de qui gère la durée de vie (Le owner) de la donner et qui utilise la donner (le borrower) que ce soit en lecture ou écriture.

    Je dirais que le seul moment ou l'on doit faire une copie, c'est lorsque l'on passe le std::shared_ptr a un autre thread. Mais dans un contexte mono-thread, il n'y a aucune raison particulière à faire une copie selon moi.

  8. #8
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    750
    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 : 750
    Par défaut
    Sans plus de détail, je dirais que si on se pose la question, c'est que soit il ne faut pas utiliser de shared_ptr, soit on veut vraiment un partage et le passage par valeur est la meilleure chose à faire.

    L'idée d'utiliser une référence non const, n'est envisageable que pour construire ou modifier le pointeur. Donc un paramètre de sortie. Et ça me semble très casse gueule.

    Quant à l'idée d'utiliser un shared_ptr sous forme de référence constante, elle n'a pas de sens. La notion de partage assurée par shared_ptr n'est pas garantie et il ne peut pas être modifié. Dans ces conditions, ce qu'on veut en réalité manipuler est une référence (au pire un pointeur nu).

    Ce n'est pas parce qu'on manipule un shared_ptr ou unique_ptr à un endroit que toutes la chaîne doit forcément manipuler le même type.

  9. #9
    Membre éclairé Avatar de Suryavarman
    Homme Profil pro
    Développeur 3D
    Inscrit en
    Mai 2006
    Messages
    233
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Développeur 3D
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Mai 2006
    Messages : 233
    Par défaut
    Woua. Merci pour chacune de vos réponses.

    Je vois que j'ai fait une grosse erreur:

    Je mettais const shared_ptr<Toto> pour interdire la modification de Toto alors que cela interdit la modification du shared_ptr. Pour obtenir ce que je voulais je dois déclarer le paramètre d'entré ainsi
    shared_ptr<const Toto>.

    Du coup ça influe beaucoup.

    Dans le cas où je manipule des std::shared_ptr<Lala> et que parfois j'utilise des fonctions qui assurent de ne pas modifier Lala
    Nous ne pouvons pas faire ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    void Toto(const std::shared_ptr<const Lala>& lala)
    {
        std::cout << lala->GetValue() << std::endl;
    }
     
    std::shared_ptr<Lala> lala = std::make_shared<Lala>();
    lala->set(3);
    Toto(lala); <---- erreur à la compilation
    Pour éviter un surplus d'écriture nous pouvons faire ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    void Toto(std::shared_ptr<const Lala> lala)
    {
        std::cout << lala->GetValue() << std::endl;
    }
     
    std::shared_ptr<Lala> lala = std::make_shared<Lala>();
    lala->set(3);
    Toto(lala);
    L'écriture est simple la conversion d'un std::shared_ptr<Lala> vers un std::shared_ptr<const Lala> se fait automatiquement. Le compteur de références est bien incrémenté.

    Mais du coup faire ça oblige à faire une copie. Et pour gagner des performances il va falloir sortir du mécanisme des std::shared_ptr
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    void TotoPerf(const Lala& lala)
    {
        std::cout << lala.GetValue() << std::endl;
    }
     
    std::shared_ptr<Lala> lala = std::make_shared<Lala>();
    lala->set(3);
    TotoPerf(*lala);
    Et si à partir de const Lala& lala il nous faut renouer avec le comptage de références depuis une instance de Lala, nous devons faire dériver Lala de https://fr.cppreference.com/w/cpp/memory/enable_shared_from_this

    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
    struct Lala : std::enable_shared_from_this<Lala>
    {
        template<typename T>
        std::shared_ptr<T> getptr() 
        {
            return std::static_pointer_cast<T>(shared_from_this());
        }
    };
     
    template <>
    std::shared_ptr<Lala> Lala::getptr() 
    {
        return shared_from_this();
    }
     
    struct Lulu : public Lala
    {};
     
    …
     
    std::shared_ptr<Lulu> lulu = std::make_shared<Lulu>();
    auto lulu2 = lulu->getptr<Lulu>();
    std::cout << lulu.use_count() << std::endl; // use_count = 2


    Jusqu'à maintenant ma ligne directrice était qu'une fois que l'instance d'un objet est confiée à un shared_ptr, nous devions alors y accéder seulement via le shared_ptr. C'est la même logique que les interfaces en .Net, une fois l'objet confié à une interface il ne doit être manipulé que via les interfaces.
    Dans des projets simples je vais pouvoir faire le choix entre un shared_ptr<const Lala> et une référence constante sur Lala. Mais sur de gros projets je préférais verrouiller le comportement et dire sauf exception nous utilisons des std::shared_ptr<Lala>.

    Maintenant ma ligne directrice va être plus compliquée.

    Je vais devoir pratiquer plus.

    Merci à tous.


    PS:
    Astraya: Merci pour le lien https://quick-bench.com je ne connaissais pas.

    Ps bis:
    Je mets résolu sans choisir une réponse plus qu'une autre.

  10. #10
    Membre éclairé Avatar de Suryavarman
    Homme Profil pro
    Développeur 3D
    Inscrit en
    Mai 2006
    Messages
    233
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Développeur 3D
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Mai 2006
    Messages : 233
    Par défaut
    Dans le cas où j'utilise une politique de faire un minimum de copie et un de mélanger le moins possible les pointeurs partagés avec des référence sur l'instance de l'objet, je souhaite utiliser des fonctions comme celles-ci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    void Toto(const std::shared_ptr<const Lala>& lala)
    {
        std::cout << lala->GetValue() << std::endl;
    }
    Pour que cela soit pratique cela oblige à faire évoluer la notion de shared_ptr pour qu'il offre un accès à une référence sur un sharde_ptr<const T>

    Un truc du genre simplifier
    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
     
    template<typename T>
    class shared_ptr: public std::shared_ptr<T>
    {
        public:
            typedef std::shared_ptr<const T> const_type;
     
        private:
            const_type m_Const;
     
        public:
            shared_ptr(T* ptr):
            m_Const(ptr)
            {}
     
            const_type& get_ref_const() const
            {
                return m_Const;
            }
    }
    En pratique c'est pas très jolie non plus. Et puis cela réduit pas mal l'utilisation des fonctionnalité de la std avec les std::shared_ptr.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    shared_ptr<Lala> lala {new Lala()};
    lala->set(3);
    Toto(lala.get_ref_const());
    Vous résoudriez ça comment?

  11. #11
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    750
    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 : 750
    Par défaut
    En utilisant les constructeurs qui font tout seul les conversions... La conversion de shared_ptr<T> vers shared_ptr<T const> est automatique.

    Mais encore une fois, avoir une référence constante sur shared_ptr en paramètre de fonction n'a pas de sens. Le but de shared est d'être copier pour garantir la durée de vie du pointeur tout au long de son utilisation lorsqu'il y a plusieurs chemins non prédictibles qui peuvent supprimer le pointeur. C’est-à-dire qu'il y a plusieurs propriétaires du pointeur et qu'il n'est pas possible de déterminer qui sera en charge de réellement supprimer le pointeur: la responsabilité est partagée.

    Ton exemple avec Toto n'est pas un partage de responsabilité. La seule chose que fait la fonction est d'utiliser le référé, elle n'a pas besoin de partager la responsabilité de destruction puisque le responsable de la destruction du pointeur est son appelant. En utilisant un shared_ptr (constant ou pas), ton interface fait trop chose.

    De plus, cette interface n'empêche en rien la copie. Avoir un type en const& n'est absolument pas une garantie d'interdiction de copie, c'est la possibilité ne pas en faire. Sans compter que ton interface supplémentaire crée 2 pointeurs intelligents dont 1 qui ne sera probablement pas nécessaire la majorité du temps.

    Ton erreur est de croire que shared_ptr est une interface qui étant un type, ce n'est pas le cas. Shared_ptr est plus proche d'un container: il stocke l'élément et se charge de le détruire en même temps que lui. Mais ils n'utilisent aucun membre de l'objet, il ne l’étend pas. Il ne s'occupe que de sa durée de vie. Comme son "interface" (si on peut parler ainsi) ne concerne que la durée de vie, il n'y aucune raison de refiler cette information aux fonctions qui n'ont pas besoin de s'occuper de la durée de vie.

  12. #12
    Membre Expert Avatar de Astraya
    Homme Profil pro
    Consommateur de café
    Inscrit en
    Mai 2007
    Messages
    1 048
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Consommateur de café
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2007
    Messages : 1 048
    Par défaut
    Je suis d'accord avec jo_link_noir. J'irais même plus loin en disant que même un pointeur nu n'a pas sa place, juste une référence constante ou pas sur l'objet contenu.

    Le std::shared_ptr étant garant de la durée de vie du l'objet, on peut assumer qu'il sera toujours valide au moment de son déréférencement, de toute façon tu auras une exception système si tu le fais et que l'objet n'existe plus.

    Il faut voir que dans ta fonction d'exemple Toto devrait prendre une référence constante et ne devrait pas connaitre la notion même de shared_ptr.
    La référence en C++ permet de s'affranchir du test à nullptr et ainsi tu peux assainir toute ta pile d'appelle de fonction en ne passant que des références, plus de copie, plus de pointeur nulle possible ( Dans la mesure ou la référence est toujours sur un objet valide ). Tu ne pose plus la question de la performance, ni de la durée de vie de l'objet ou du pointeur, si il y a un problème, il doit être traité par l'appelant de la fonction.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    void Toto(const Lala& lala) { 
        std::cout << lala.GetValue() << std::endl; // Peu importe la durée de vie, le owner de Lala, la fonction considère que c'est un Lala OK!
    }
    
    void Appelant() {
       if(the_shared_ptr){
          Toto(*the_shared_ptr);
       }
    }

  13. #13
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 633
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 633
    Par défaut
    Salut,

    D'ailleurs, on pourrait même encore aller plus loin que jo_link et Astraya... :

    Dans l'idéal, shared_ptr ne devrait être utilisé que lorsque l'on n'a vraiment pas le choix.

    Car la différence entre shared_ptr et unique_ptr, c'est uniquement que unique_ptr ne peut être "possédé" que par un seul et unique propriétaire, mais cela n'empêche différents "prorpriétaires potentiels" de se "refiler la patate chaude". Du moins, aussi longtemps que la patate passe de main en main, et qu'elle ne se trouve jamais que dans une seule et unique main

    Il n'y aura, au final, que lorsque plusieurs éléments peuvent prétendre au droit de libérer la ressources en même temps qu'il deviendra nécessaire d'organiser un peu tout cela selon le principe de "le dernier éteint la lumière et ferme la porte" proposé par shared_ptr.

    Or, il est parfaitement réaliste de n'avoir qu'un seul et unique élément responsable de la libération des ressources "à un instant T", et c'est ce qu'il est largement conseillé de faire dans la très grosse majorité des cas
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  14. #14
    Membre éclairé Avatar de Suryavarman
    Homme Profil pro
    Développeur 3D
    Inscrit en
    Mai 2006
    Messages
    233
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Développeur 3D
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Mai 2006
    Messages : 233
    Par défaut
    Merci à tous.
    Je vais maintenant faire mes nouvelles armes avec ces nouvelles notions/dimensions pour moi.

    shared_ptr<T>
    shared_ptr<const T>
    weak_ptr<T>
    weak_ptr<const T>
    T&
    const T&

    Mon projet perso est basé sur les shared_ptr et là j’ai de quoi réfléchir.

    Encore merci à tous. Chapeau bas.

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

Discussions similaires

  1. [POO] Passage de paramètre par référence.
    Par abidi_niz dans le forum Langage
    Réponses: 3
    Dernier message: 12/10/2006, 12h20
  2. Passage par copie vs passage par référence
    Par bolhrak dans le forum C++
    Réponses: 11
    Dernier message: 20/08/2006, 23h37
  3. [C#] passage de paramètres par référence
    Par SesechXP dans le forum Windows Forms
    Réponses: 3
    Dernier message: 03/08/2006, 12h48
  4. [C#] Envoie des paramètres par référence
    Par efficks dans le forum C#
    Réponses: 4
    Dernier message: 29/11/2005, 23h53
  5. [EJB] Passage des paramètres par référence
    Par salome dans le forum Java EE
    Réponses: 2
    Dernier message: 05/07/2005, 11h25

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