2015-04-11 3 views
2

Оба раздела кода, приведенные ниже, значительно упрощены, изолированные версии моего фактического кода. Примеры достаточно велики, чтобы воспроизвести проблему. Первый раздел кода ниже работает отлично. Секция раздела - это попытка начать делать ее частью класса. Я пытаюсь сделать крошечные шаги, поскольку небольшие изменения в чем-то вроде структуры, показанной ниже, требуют большого количества изменений во всем коде, который полон указателей, указатель на указатели и ссылки, которые все связаны с этой структурой. Можете ли вы рассказать мне, почему вторая часть кода вызывает переполнение стека внутри своего конструктора и какие небольшие изменения могут быть внесены для его исправления?Проблема с конструктором struct, вызывающим переполнение стека

Рабочий код:

#include <cstdio> 
#include <cstdlib> 
#include <iostream> 

using std::cout; 
using std::endl; 

const int maxSize = 3; 

struct Item{ 
    int count; 
    Item *items[maxSize + 1]; 
}; 

void foo() 
{ 
    Item *p; 
    p = new Item(); 
    p->count = 2; 
    cout << p->count << endl; 
} 

int main(int argc, char *argv[]) 
{ 
    foo(); 
    return 0; 
} 

Попытка очень постепенно изменять код в целом к ​​превращению в класс:

#include <cstdio> 
#include <cstdlib> 
#include <iostream> 

using std::cout; 
using std::endl; 

int maxSize = 3; 

struct Item{ 
    int count; 
    Item *items; 

    Item() 
    { 
     items = new Item[maxSize + 1]; // stack overflow 
    } 
}; 

void Initialize(int size) 
{ 
    maxSize = size; 
} 

void foo() 
{ 
    Item *p; 
    p = new Item(); 
    p->count = 2; 
    cout << p->count << endl; 
} 

int main(int argc, char *argv[]) 
{ 
    Initialize(5); 
    foo(); 
    return 0; 
} 
+0

Вы только что создали рекурсию ... –

ответ

1

Все ответы правильные. Я хочу предложить для вас решение: Вместо инициализации массива в пределах CTOR, вы могли бы реализовать метод инициализации как

init(int maxSize) { 
    items = new Item[maxSize + 1]; 
} 

, что вы можете позвонить после того, как построив объект. Это должно избежать переполнения стека. В общем, вам следует избегать размещения экземпляров объекта внутри самого объекта. Лучше использовать Коллекции предмета List<Item>, std::vector<Item>, ...

1

Это потому, что в рабочей версии у вас есть ссылка на массив объекта , но не фактический объект Items. Во второй версии вы создаете объекты, используя ключевое слово new. Итак, во второй версии в конструкторе он будет называть себя! Он будет называть его собственным конструктором бесконечным временем. Таким образом, вы видите во время выполнения исключение StackOverflow :)

2

Первый вызов построить Item вызовов new Item[maxSize+1], который вызывает конструктор по умолчанию, который вызывает new Item[maxSize+1], который вызывает конструкцию по умолчанию, и так далее, пока вы не достигнете переполнения стека.

0

Над плакатами находятся правые. Внутри конструктора Item вы создаете элементы (путем создания массива). Таким образом, ctor снова вызывается, что создает больше предметов, которые ... Это более или менее бесконечный цикл, который ест ваш стек. Либо придерживайтесь ссылок или используйте коллекцию, как List - так что вы можете добавить элементы позже динамически.

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