Infinite loop in constructor without for or while

C++RecursionConstructorConstants

C++ Problem Overview


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;  
}

C++ Solutions


Solution 1 - C++

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!

Solution 2 - C++

the problem is from constructor you again calling the contructor test(_b)

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

here is what happens

everytime you call test(_b) it first calls default constructor test::test and it in turns calls the test(_b) and the loop goes on and on untill the stack overflows.

remove the test(_b) from the default constructor

Solution 3 - C++

I'm not familiar with the particularities of the standard, but it may be that calling a constructor within a constructor is undefined. As such it could be compiler dependent. In this particular case it causes infinite recursion of your default constructor without ever calling your constructor with the map argument.

C++ FAQ 10.3 has an example with a constructor that has two parameters. If you add an int parameters to your second constructor such as test(map, int), it exhibits a somewhat normal behaviour.

For good form I would simply change test::test(std::map <int, int>& im) for test::testInit(std::map <int, int>& im), and test(_b) to testInit(_b).

Solution 4 - C++

I'm pretty sure that you are not actually "calling the constructor" since they are not directly callable IIRC. The legalese had to do with constructors not being named functions - I don't have a copy of the Standard handy or I might quote it. I believe what you are doing with test(_b) is creating an unnamed a temporary which invokes the default constructor again.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionCJAN.LEEView Question on Stackoverflow
Solution 1 - C++templatetypedefView Answer on Stackoverflow
Solution 2 - C++PradheepView Answer on Stackoverflow
Solution 3 - C++OlivierDView Answer on Stackoverflow
Solution 4 - C++D.ShawleyView Answer on Stackoverflow