2010-05-29 2 views
0

Я нашел это странное поведение с компилятором VS2005 C++. Вот так:Константный параметр в конструкторе вызывает stackoverflow

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

Вот исходный код: он работает отлично

class Foo { 
    public: 
    Foo(Bar &bar) { ... } 
} 

Конструктор реализация сохраняет ссылку, настройки некоторых членов ... действительно ничего особенного.

Если изменить код следующим образом:

class Foo { 
    public: 
    Foo(const Bar &bar) { ... } 
} 

я добавил константный спецификатора единственным параметром конструктора рутинного.

Он компилируется правильно, но компилятор выводит предупреждение о том, что подпрограмма Foo :: Foo вызовет stackoverflow (даже если путь выполнения не создает объект Foo); эффективно это происходит.

Итак, почему код без сопзЬ параметра отлично работает, в то время как один с Const классификатором вызывает StackOverflow? Что может вызвать это странное поведение?

+2

Вам нужно размещать как код и предупреждение компилятора вы получаете. – 2010-05-29 08:53:14

+4

Невозможно рассказать об этой информации. Нам нужна намного больше информации или минимальный фрагмент кода, с помощью которого можно воспроизвести предупреждение – Naveen

+0

Действительно? У меня VS2005 с версией 15.00.30729.01 компилятора C++, и оба фрагмента кода (с помощью 'class Bar {};') не дают мне никаких предупреждений о переполнении стека даже на самом высоком уровне предупреждения. Я что-то упускаю? –

ответ

2

Единственный способом для этого, чтобы вызвать переполнение стеки (кроме ошибки в компиляторе, который, в моих 15 годах выполнения C++, я нашел редкий по сравнению с моими собственными ошибками) является то, что Foo(const Bar&) создает Foo объекта передавая его Bar объект. Ошибки, подобные этим, могут быть сложными и сложными, если посмотреть на код.

Но если у вас есть VS2005, у вас есть довольно хороший отладчик под рукой. Поместите контрольную точку в этот конструктор, запустите программу, пока не нажмете точку останова, а затем запустите снова, пока вы не нажмете точку останова во второй раз. Рассмотрение стека покажет вам, как это происходит.

Если не каждый вызов конструктора вызовет переполнение стека, вы можете добавить этот код:

namespace { unsigned int recursion_detector = 0; } 

Foo::foo(const Bar& bar) 
{ 
    if(recursion_detector++) 
    ++recursion_detector; // meaningless code just to put a breakpoint here 
    // rest of constructor code 
} 

и поставить точку останова на строке указано, что будет удар, когда происходит рекурсия.

4

Попробуйте ввести ключевое слово explicit?

Я предполагаю, что с const вы объявляете автоматическое преобразование из Bar в Foo; и если у вас уже есть автоматическое преобразование с Foo в Bar, то переполнение?

0

Вы можете изменить параметр из const bar & bar to const Bar * bar. Он будет работать нормально, вам просто нужно изменить способ управления панелью параметров (от референта до указателя).

инициализации объекта будет что-то вроде:

Bar mybar; 

... 

Foo myfoo(&mybar); 


class Foo { 
    public: 
    Foo(const Bar *bar) { ... } 
}; 

Это не так уж плохо ...

Смежные вопросы