2010-10-11 8 views
2

Un ami m'a envoyé ceci et je ne sais vraiment pas ce que c'est, à l'intérieur de la boucle. Quoi qu'il en soit, il appelle le constructeur std :: set un demi-million de fois ... toute aide appréciée. Je pense une erreur du compilateur, mais il compile en fait en g ++ 4.4 et 4.5 et le comportement est différent de copier la construction ...Syntaxe C++ invisible

#include <stdio.h> 
#include <stdlib.h> 
#include <boost/unordered_map.hpp> 
#include <set> 
#include <string> 

typedef boost::unordered_map<int, std::set<int> > mymap; 

int main() { 
    mymap map; 
    for (int i = 0 ; i < 1000 ; i++)  
    { 
     std::set<int> map[i] ; 
    } 
    return 1; 
}; 
+0

Est-ce une question? – YeenFei

+1

Le code ne devrait même pas être compilé. Quelle est votre question? – GManNickG

+0

En C++ utiliser et Abyx

Répondre

12

Vous avez affaire à une extension non-standard du langage C++ spécifique à GCC. Chaque itération définit un tableau d'objets std::map avec i éléments (et le détruit immédiatement).

En C++ standard, il est illégal d'utiliser une expression non constante pour spécifier la taille d'un tableau, donc le code n'est pas C++ légal. Il compile, encore une fois, seulement parce que GCC le permet comme une extension.

0

Le même code est

struct Foo {}; 

int main() 
{ 
    int i = 100; 
    Foo map[i]; 
} 

Il est une déclaration de la variable "map" de type "tableau de Foo"; Ce tableau a une taille dynamique i.

+3

Cela ne devrait pas compiler en C++. Certains compilateurs peuvent le faire, mais ce n'est pas tout à fait correct. – JoshD

+0

@Josh @GMan sauf s'il s'agit d'un VLA C99 utilisé par GCC en code C++. Compiler ceci avec '-pedantic' me donne' un avertissement: ISO C++ interdit le tableau de longueur variable 'map''. –

0

Lors de l'itération i de la boucle, vous créez un tableau de i std :: sets. Le nombre total créé est donc i (i + 1)/2 = 500500.

+0

C'est ce qu'il ferait s'il compilé;) – Grozz

+0

Je devine qu'il voulait savoir pourquoi il avait tant d'appels de constructeur. En tout cas, le code qui fait essentiellement la même chose se compile pour moi (g ++ 4.1.2 - mais je n'ai pas de boost donc j'ai utilisé un typedef différent). – Kricket

-1

Je vois les erreurs de compilation suivantes

alias g++ 
alias g++='g++ -ansi -pedantic -Wall -W -Wconversion -Wshadow -Wcast-qual -Wwrite-strings' 

c.cpp: In function ‘int main()’: 
c.cpp:10: warning: ISO C++ forbids variable length array ‘map’ 
c.cpp:10: warning: declaration of ‘map’ shadows a previous local 
c.cpp:7: warning: shadowed declaration is here 
c.cpp:10: warning: unused variable ‘map’ 
+0

Je vois des avertissements, pas d'erreurs ... – kay

+1

true; mais je compile toujours avec '-Werror' pour traiter les avertissements comme des erreurs :-) – Arun

1

AndreyT déjà à peu près répondu à la question, mais voici une définition plus détaillée:

tableaux automatiques de longueur variable sont autorisés dans la norme ISO C99, et en tant qu'extension , GCC les accepte en mode C90 et en C++. (Cependant, de GCC mise en œuvre de longueur variable tableaux ne se conforme pas encore en détail à la norme ISO C99.) Ces tableaux sont déclarés comme tout autre automatique des tableaux, mais avec une longueur qui n'est pas une expression constante. Le stockage est affecté au point de la déclaration et désalloué lorsque le niveau d'accolade est quitté. Par exemple:

FILE * 
concat_fopen (char *s1, char *s2, char *mode) 
{ 
    char str[strlen (s1) + strlen (s2) + 1]; 
    strcpy (str, s1); 
    strcat (str, s2); 
    return fopen (str, mode); 
} 

Vous ne devriez pas utiliser VLA (en C++) OUalloca() (comme la documentation GCC suggère à http://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html) car ils sont tous deux considérés comme assez pratique "meh". Ils peuvent tous deux entraîner des débordements de pile et/ou un comportement indéfini.

Modifier: lire la documentation de GCC de plus près et regarder

int tester (int len, char data[len][len]) 
{ 
    /* ... */ 
} 

.. J'espère sérieusement n'écrit le code comme ça. Je suppose que c'est une fonctionnalité intéressante, mais quand même ... wtf?