Unseen C++ syntax
A friend sent me this and I really don't know 开发者_开发百科what it is, inside the loop. Whatever it be it calls the std::set constructor half million times.... any help appreciated. I would expect a compiler error, but it actually compiles in g++ 4.4 and 4.5 and the behavior is different to copy construction...
#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;
};
You are dealing with a GCC-specific non-standard extension of C++ language. Each iteration defines an array of std::map
objects with i
elements (and immediately destroys it).
In standard C++ it is illegal to use a non-constant expression to specify array size, so the code is not legal C++. It compiles, again, only because GCC allows it as an extension.
AndreyT already pretty much answered the question, but here's a more verbose definition:
Variable-length automatic arrays are allowed in ISO C99, and as an extension GCC accepts them in C90 mode and in C++. (However, GCC's implementation of variable-length arrays does not yet conform in detail to the ISO C99 standard.) These arrays are declared like any other automatic arrays, but with a length that is not a constant expression. The storage is allocated at the point of declaration and deallocated when the brace-level is exited. For example:
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);
}
You shouldn't use VLAs (in C++) OR alloca()
(as the GCC documentation suggests at http://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html) as they are both considered pretty "meh" practice. They can both lead to stack overflows and/or undefined behavior.
Edit: reading the GCC documentation more closely and looking at
int tester (int len, char data[len][len])
{
/* ... */
}
.. I seriously hope no one writes code like that. I guess it's a cool feature, but still... wtf?
The same code is
struct Foo {};
int main()
{
int i = 100;
Foo map[i];
}
It's a declaration of variable "map" of type "array of Foo"; This array has a dynamic size i.
On iteration i of the loop, you create an array of i std::sets. The total number created is thus i(i+1)/2 = 500500.
I see the following compilation errors
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’
精彩评论