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 :

Variable dans un namespace anonyme et fonction inline


Sujet :

C++

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Juin 2010
    Messages
    16
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2010
    Messages : 16
    Par défaut Variable dans un namespace anonyme et fonction inline
    Bonjour,

    J'ai "resolu" aujourd'hui (sans doute par un coup de chance...) un soucis que j'avais et qui a fortement attise ma curiosite. Je vais reproduire en simplifie le soucis ici afin de poser ma question :p

    Voici un header (file.hh)
    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
    #ifndef FILE_HH
    # define FILE_HH
     
    namespace ns
    {
     
      namespace
      {
        int var = 0;
      } // namespace
     
      void incrVar();
     
      void foo();
     
    } // namespace ns
     
    # include "file.hxx"
     
    #endif // !FILE_HH
    La fonction 'ns::incrVar()' est inline. Elle incremente 'var' et affiche sa nouvelle valeur (file.hxx)
    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
    #ifndef FILE_HXX
    # define FILE_HXX
     
    # include <iostream>
     
    # include "file.hh"
     
    namespace ns
    {
     
      inline
      void
      incrVar()
      {
        ++var;
        std::cout << "incrVar(): " << var << std::endl;
      }
     
    } // namespace ns
     
    #endif // !FILE_HXX
    Et enfin, la fonction 'ns::foo()', qui ne fait qu'afficher la valeur de 'var' (file.cc)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    #include <iostream>
     
    #include "file.hh"
     
    namespace ns
    {
     
      void
      foo()
      {
        std::cout << "foo(): " << var << std::endl;
      }
     
    } // namespace ns
    Faisons des tests avec une fonction 'main()' (main.cc)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #include <iostream>
     
    #include "file.hh"
     
    int
    main()
    {
      ns::incrVar();
      ns::incrVar();
      ns::incrVar();
      ns::foo();
    }
    Pas de warning ni d'erreur a la compilation, alors c'est parti...

    Si l'on m'avait pose la question "Quel sera le contenu de la sortie standard ?", j'aurais sans hesite repondu :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    incrVar(): 1
    incrVar(): 2
    incrVar(): 3
    foo(): 3
    ... Et je me serais trompe : la valeur de 'var' affichee par ns::foo() est '0' (et non '3').
    Pour que 'ns::foo()' affiche '3', il aurait fallu que 'ns::incrVar()' soit dans le .cc, et donc pas inline. (Dans ce cas, on aurait un warning pour une variable non utilisee, mais ca "fonctionnerait").

    Donc la, pour moi, ca devient assez bizarre : une variable dans un namespace anonyme serait accessibe dans le header et les sources, mais n'aurait pas la meme valeur dans le .hh (ou .hxx) et dans le .cc ??

    Il y a tres certainement une explication... et c'est ce que je vous demande ici

    Merci d'avance ^^ (C'est pas presse, c'est de la curiosite :p)


    PS : desole pour les accents :s

  2. #2
    Membre Expert

    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 : 34
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Par défaut
    Bonsoir,

    Alors lorsque tu compiles un fichier (donc .c/.cpp/.C/etc) le préprocesseur va inclure l'ensmble des fichier indiqué dans les directives préprocesseur, ceci constitue une unité de compilation (TU). Un namespace anonyme est un namespace qui aura un nom différent par TU et qui parcouru sans avoir besoin de le préciser lors de la recherche des identifiants.

    Dans ton cas tu as deux TU, celle issue de main.cc et celle issue de file.cc. Disons que dans main.cc le "nom" du namespace anonyme est NS_MAIN et que dans file.cc c'est NS_FILE.

    Donc dans ton premier cas, la fonction foo est définie dans le TU issue de file.cc et donc lors de l'utilisation de la fonction inline incrVar (pour simplifier dans un premier temps, disons qu'une fonction inline c'est comme avoir écrit directement le code au niveau de l'appel) c'est la variable ns::NS_FILE::var qui est utilisé. Et donc de la même manière c'est la variable ns::NS_MAIN::var qui est utilisé lors de l'appel de la fonction incrVar dans le TU issue de main.cc.

    Dans le second cas, ta fonction incrVar n'est plus inline, et c'est donc toujours ns::NS_FILE::var qui est utilisé (car incrVar est définie dans le TU issue de file.cc dans ce second cas).

    Un dernier détail qui a son importance. La norme nous dit qu'une fonction inline doit avoir exactement la même définition dans chaque TU, or le fait que dans ton premier cas elle utilise pas la même variable selon le TU d'où elle est appelé ne remplit pas cette condition. Ton premier test est donc un comportement indéfinie en réalité (UB).

    Je ne sais pas si mon explication est très clair , n'hésite pas à le dire si ce n'est pas le cas

  3. #3
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 147
    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 147
    Billets dans le blog
    4
    Par défaut
    Bonjour,

    il y a bien une entrée dans la FAQ, mais on travaille à la faire évoluer.
    Ce sur quoi nous sommes plus ou moins d'accord c'est que le namespace anonyme ne devrait pas être utilisé dans un header, mais uniquement dans un fichier compilé.
    Ca évitera les erreurs comme celle-ci.

    Sinon, plutôt qu'un namespace anonyme et des fonctions libres, si tu encapsules tout ça dans une classe, le comportement devrait être celui attendu.
    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.

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Juin 2010
    Messages
    16
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2010
    Messages : 16
    Par défaut
    Bonjour,

    Merci, une reponse precise

    Un namespace anonyme est un namespace qui aura un nom différent par TU
    Dans ce cas, tout s'explique
    Les precisions m'ont permises de comprendre encore plus vite, c'est parfait ^^

    Effectivement, un namespace anonyme dans un header devient "moche" et meme risques... Ils seront bannis ! ><

    Sinon, plutôt qu'un namespace anonyme et des fonctions libres, si tu encapsules tout ça dans une classe, le comportement devrait être celui attendu.
    Je pense que c'est une question de gout : soit creer les fonctions en 'static' dans une classe, soit creer les fonctions dans un namespace (nomme)... En plus, dans mon cas, j'aurais sans doute juste du reflechir un peu plus : je souhaite avoir une variable qui ne soit pas visible hors d'un .cc (accessible via des fonctions uniquement), pourquoi la declarer dans le header ? ><

    Quoi qu'il en soit, avoir fait cette erreur, ca m'a permi de poster ici puis d'apprendre quelque chose d'interessant sur un namespace anonyme, donc je suis content ^^

    Merci encore a vous :p

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

Discussions similaires

  1. [XL-2007] Insérer une variable dans les paramètre d'un fonction
    Par anolo40 dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 17/01/2011, 21h08
  2. [Google Maps] Extraire une locale variable dans une fonction anonyme
    Par 3logy dans le forum APIs Google
    Réponses: 4
    Dernier message: 17/12/2010, 12h02
  3. Réponses: 0
    Dernier message: 18/05/2010, 22h19
  4. Importer via asp.net c# des variables dans mon namespace xsl
    Par akaii dans le forum XSL/XSLT/XPATH
    Réponses: 2
    Dernier message: 23/01/2006, 08h41
  5. [AS2] déclarer des variables dans une fonction
    Par ooyeah dans le forum ActionScript 1 & ActionScript 2
    Réponses: 12
    Dernier message: 02/08/2005, 12h50

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