开发者

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’
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜