Infinite loop in constructor without for or while

I did a test here, but the output is a loop without ending, I don't know why.

Actually, I am doing another test, but when I wrote this, I don't understand how the loop occurred. It is output "ABC" repeatedly.

#include <map>
#include <string>
#include <iostream>

class test
{
public:
   std::map <int, int> _b;
   test();
   test (std::map<int, int> & im);
   ~test();
   };

test::test()
{
  std::cout<<"abc";
  _b.clear();
  _b[1]=1;
  test(_b);
}

test::test(std::map <int, int>& im)
{
   std::cout<<im[1];
}

test::~test() {};

int main ()
{
   test a;  
}

The issue here is that the compiler interprets

test(_b);

Not as code that creates a temporary object of type test passing in parameter _b, but as a variable declaration for a variable named _b of type test, using the default constructor. Consequently, what looks like a piece of code that creates a temporary test object using the second constructor is instead recursively creating a new object of type test and invoking the constructor another time.

To fix this, you can give the variable an explicit name, such as

test t(_b);

This can only be interpreted as a variable of type test named t, initialized using the second constructor.

I have never seen this before, and I've been programming in C++ for years. Thanks for showing me yet another corner case of the language!

For an official explanation: According to the C++03 ISO spec, §6.8:

There is an ambiguity in the grammar involving expression-statements and declarations: An expression-statement with a function-style explicit type conversion (5.2.3) as its leftmost subexpression can be indistinguishable from a declaration where the first declarator starts with a (. In those cases the statement is a declaration.

(My emphasis). In other words, any time C++ could interpret a statement as either an expression (the temporary object cast) or as a declaration (of a variable), it will pick the declaration. The C++ spec explicitly gives

T(a);

As an example of a declaration, not a cast of a to something of type T.

This is C++'s Most Vexing Parse - what looks like an expression is instead getting interpreted as a declaration. I've seen the MVP before, but I have never seen it in this context.

Hope this helps!