Бесконечный цикл в конструкторе без for или while


Я сделал тест здесь, но выход-это цикл без конца, я не знаю, почему.

на самом деле, я делаю еще один тест, но когда я написал это, я не понимаю, как цикл произошел. Выводится" ABC " многократно.

#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;  
}
4   60   2013-04-24 23:51:49

4 ответа:

проблема здесь в том, что компилятор интерпретирует

test(_b);

не как код, который создает временный объект типа test передача параметра _b, а как объявление переменной для переменной _b типа test, используя конструктор по умолчанию. Следовательно, то, что выглядит как кусок кода, который создает временный test объект, использующий второй конструктор, вместо этого рекурсивно создает новый объект типа test и вызов конструктора другой раз.

чтобы исправить это, вы можете дать переменной явное имя, например

test t(_b);

это можно интерпретировать только как переменную типа test имени t инициализируется с помощью второго конструктора.

я никогда видел это раньше, и я уже много лет программирую на C++. Спасибо, что показали мне еще один угловой случай языка!

для официального объяснения: согласно к спецификации ISO C++03, §6.8:

существует неоднозначность в грамматике, включающей выражения-операторы и объявления: выражение-оператор с явным преобразованием типа в стиле функции (5.2.3), поскольку его крайнее левое подвыражение может быть неотличимо от объявления, где первый Декларатор начинается с (. в этих случаях заявление, декларация.

(Курсив мой). Другими словами, в любое время c++ может интерпретировать оператор как выражение (временное приведение объекта) или как объявление (переменной), он выберет объявление. Спецификация C++ явно дает

T (a);

в качестве примера объявления, а не приведения a что-то типа T.

это C++ ' s Самый Досадный Разбор - то, что выглядит как выражение, вместо этого интерпретируется как объявление. Я видел MVP раньше, но я никогда не видел его в этом контексте.

надеюсь, что это помогает!

проблема в том, что из конструктора вы снова вызываете тест contructor (_b)

test:: test(){std:: cout

вот что происходит

каждый раз, когда вы вызываете test(_b), он сначала вызывает конструктор по умолчанию test::test, и он по очереди вызывает тест (_b), и цикл продолжается и продолжается до тех пор, пока стек не переполнится.

удалить тест(_b) из конструктора по умолчанию

Я уверен, что вы на самом деле не "вызове конструктора" поскольку они не являются непосредственно вызываемыми IIRC. Законники имели дело с конструкторами не будучи имени функции - у меня нет копии стандарта под рукой, или я мог бы процитировать его. Я верю, что вы делаете с test(_b) создает безымянный временный, который снова вызывает конструктор по умолчанию.

Я не знаком с особенностями стандарта, но может быть, что вызов конструктора в конструкторе не определен. Как таковой он может быть зависимым от компилятора. В этом конкретном случае он вызывает бесконечную рекурсию вашего конструктора по умолчанию, никогда не вызывая ваш конструктор с аргументом map.

C++ FAQ 10.3 имеет пример с конструктором, который имеет два параметра. Если вы добавляете параметры int во второй конструктор, например test(map, int), Это проявляет несколько нормальное поведение.

для хорошей формы я бы просто изменил test::test(std::map <int, int>& im) на test::testInit(std::map <int, int>& im) и test(_b) до testInit(_b).